tx

Minimal Bitcoin transaction primitives (docs.ppad.tech/tx).
git clone git://git.ppad.tech/tx.git
Log | Files | Refs | README | LICENSE

commit a468ba5a0daee4cf6719cba659ea5272806f694b
Author: Jared Tobin <jared@jtobin.io>
Date:   Sun, 25 Jan 2026 17:43:35 +0400

Initial project skeleton for ppad-tx

Minimal Bitcoin transaction primitives library, following ppad
conventions (Bitcoin.Prim.* namespace, nix flake, LLVM support).

Modules:
- Bitcoin.Prim.Tx: core types (Tx, TxIn, TxOut, OutPoint, Witness, TxId)
  and serialisation stubs
- Bitcoin.Prim.Tx.Sighash: sighash types and computation stubs

Dependencies: ppad-sha256, ppad-base16.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Diffstat:
A.gitignore | 1+
AAGENTS.md | 141+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ACHANGELOG | 4++++
ACLAUDE.md | 141+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ALICENSE | 20++++++++++++++++++++
Abench/Main.hs | 44++++++++++++++++++++++++++++++++++++++++++++
Abench/Weight.hs | 43+++++++++++++++++++++++++++++++++++++++++++
Aflake.nix | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/Bitcoin/Prim/Tx.hs | 108+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/Bitcoin/Prim/Tx/Sighash.hs | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Appad-tx.cabal | 91+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest/Main.hs | 27+++++++++++++++++++++++++++
12 files changed, 773 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1 @@ +dist-newstyle/ diff --git a/AGENTS.md b/AGENTS.md @@ -0,0 +1,141 @@ +# ppad-tx + +Minimal Bitcoin transaction primitives for ppad libraries. + +## Project Structure + +- `lib/` - library source (Bitcoin.Prim.Tx) +- `test/` - tests (tasty + tasty-hunit) +- `bench/` - benchmarks (criterion for timing, weigh for allocations) +- `flake.nix` - nix flake for dependency and build management +- `ppad-tx.cabal` - cabal package definition +- `CLAUDE.md` / `AGENTS.md` - keep these in sync + +## Build and Test + +Enter devshell and use cabal: + +``` +nix develop +cabal build +cabal test +cabal bench +``` + +Do not use stack. All dependency and build management via nix. + +## Dependencies + +### ppad libraries (use freely) + +Use ppad libraries (github.com/ppad-tech, git.ppad.tech) liberally. +Current dependencies: ppad-sha256, ppad-base16. + +### External libraries + +Use only minimal external dependencies. Prefer GHC's core/boot libraries +(base, bytestring, primitive, etc.). + +**Ask for explicit confirmation before adding any library outside of:** +- GHC boot/core libraries +- ppad-* libraries +- Test dependencies (tasty, QuickCheck, etc. for test-suite only) +- Benchmark dependencies (criterion, weigh for benchmark only) + +## Code Style + +### Performance + +- Use strictness annotations (BangPatterns) liberally +- Prefer UNPACK for strict record fields +- Use MagicHash, UnboxedTuples, GHC.Exts for hot paths +- Do not rely on UNBOX pragmas; implement primitives directly with + MagicHash and GHC.Exts when needed +- Use INLINE pragmas for small functions +- Refer to ppad-sha256 and ppad-fixed for low-level patterns + +### Type safety + +- Encode invariants into the type system +- Use newtypes liberally (e.g., TxId, Satoshi) +- Use ADTs to make illegal states unrepresentable +- Prefer smart constructors that validate inputs + +### Safety + +- Never use partial Prelude functions (head, tail, !!, etc.) +- Avoid brittle partials in tests too (e.g., unchecked indexing). Prefer + bounds checks or total helpers even in test code. +- Avoid non-exhaustive pattern matches and unsafe behavior; use total + helpers and make all constructors explicit. +- Use Maybe/Either for fallible operations +- Validate all inputs at system boundaries + +### Formatting + +- Keep lines under 80 characters +- Use Haskell2010 +- Module header with copyright, license, maintainer +- OPTIONS_HADDOCK prune for public modules +- Haddock examples for exported functions + +## Testing + +Use tasty to wrap all tests: +- tasty-hunit for unit tests with known vectors +- tasty-quickcheck for property-based tests +- Source test vectors from BIPs (BIP143), Bitcoin Core tx_valid.json + +Property tests should enforce invariants that can't be encoded in types. + +## Benchmarking + +Always maintain benchmark suites: +- `bench/Main.hs` - criterion for wall-time benchmarks +- `bench/Weight.hs` - weigh for allocation tracking + +Define NFData instances for types that need benchmarking. + +## Git Workflow + +- Feature branches for development; commit freely there +- Logical, atomic commits on feature branches +- Master should be mostly merge commits +- Merge to master with `--no-ff` after validation +- Always build and test before creating a merge commit +- Write detailed merge commit messages summarising changes + +### Worktree flow (for planned work) + +When starting work on an implementation plan: + +``` +git worktree add ./impl-<desc> -b impl/<desc> master +# work in that worktree +# merge to master when complete +git worktree remove ./impl-<desc> +``` + +### Commits + +- Higher-level descriptions in merge commits +- Never update git config +- Never use destructive git commands (push --force, hard reset) without + explicit request +- Never skip hooks unless explicitly requested + +## Planning + +When planning work: +- Highlight which steps can be done independently +- Consider forking subagents for concurrent work on independent steps +- Write implementation plans to `plans/IMPL<n>.md` if the project uses + this convention + +## Flake Structure + +The flake.nix follows ppad conventions: +- Uses ppad-nixpkgs as base +- Follows references to avoid duplication +- Supports LLVM backend via cabal flag +- Provides devShell with ghc, cabal, cc, llvm diff --git a/CHANGELOG b/CHANGELOG @@ -0,0 +1,4 @@ +# Changelog + +- 0.1.0 (UNRELEASED) + * Initial release. diff --git a/CLAUDE.md b/CLAUDE.md @@ -0,0 +1,141 @@ +# ppad-tx + +Minimal Bitcoin transaction primitives for ppad libraries. + +## Project Structure + +- `lib/` - library source (Bitcoin.Prim.Tx) +- `test/` - tests (tasty + tasty-hunit) +- `bench/` - benchmarks (criterion for timing, weigh for allocations) +- `flake.nix` - nix flake for dependency and build management +- `ppad-tx.cabal` - cabal package definition +- `CLAUDE.md` / `AGENTS.md` - keep these in sync + +## Build and Test + +Enter devshell and use cabal: + +``` +nix develop +cabal build +cabal test +cabal bench +``` + +Do not use stack. All dependency and build management via nix. + +## Dependencies + +### ppad libraries (use freely) + +Use ppad libraries (github.com/ppad-tech, git.ppad.tech) liberally. +Current dependencies: ppad-sha256, ppad-base16. + +### External libraries + +Use only minimal external dependencies. Prefer GHC's core/boot libraries +(base, bytestring, primitive, etc.). + +**Ask for explicit confirmation before adding any library outside of:** +- GHC boot/core libraries +- ppad-* libraries +- Test dependencies (tasty, QuickCheck, etc. for test-suite only) +- Benchmark dependencies (criterion, weigh for benchmark only) + +## Code Style + +### Performance + +- Use strictness annotations (BangPatterns) liberally +- Prefer UNPACK for strict record fields +- Use MagicHash, UnboxedTuples, GHC.Exts for hot paths +- Do not rely on UNBOX pragmas; implement primitives directly with + MagicHash and GHC.Exts when needed +- Use INLINE pragmas for small functions +- Refer to ppad-sha256 and ppad-fixed for low-level patterns + +### Type safety + +- Encode invariants into the type system +- Use newtypes liberally (e.g., TxId, Satoshi) +- Use ADTs to make illegal states unrepresentable +- Prefer smart constructors that validate inputs + +### Safety + +- Never use partial Prelude functions (head, tail, !!, etc.) +- Avoid brittle partials in tests too (e.g., unchecked indexing). Prefer + bounds checks or total helpers even in test code. +- Avoid non-exhaustive pattern matches and unsafe behavior; use total + helpers and make all constructors explicit. +- Use Maybe/Either for fallible operations +- Validate all inputs at system boundaries + +### Formatting + +- Keep lines under 80 characters +- Use Haskell2010 +- Module header with copyright, license, maintainer +- OPTIONS_HADDOCK prune for public modules +- Haddock examples for exported functions + +## Testing + +Use tasty to wrap all tests: +- tasty-hunit for unit tests with known vectors +- tasty-quickcheck for property-based tests +- Source test vectors from BIPs (BIP143), Bitcoin Core tx_valid.json + +Property tests should enforce invariants that can't be encoded in types. + +## Benchmarking + +Always maintain benchmark suites: +- `bench/Main.hs` - criterion for wall-time benchmarks +- `bench/Weight.hs` - weigh for allocation tracking + +Define NFData instances for types that need benchmarking. + +## Git Workflow + +- Feature branches for development; commit freely there +- Logical, atomic commits on feature branches +- Master should be mostly merge commits +- Merge to master with `--no-ff` after validation +- Always build and test before creating a merge commit +- Write detailed merge commit messages summarising changes + +### Worktree flow (for planned work) + +When starting work on an implementation plan: + +``` +git worktree add ./impl-<desc> -b impl/<desc> master +# work in that worktree +# merge to master when complete +git worktree remove ./impl-<desc> +``` + +### Commits + +- Higher-level descriptions in merge commits +- Never update git config +- Never use destructive git commands (push --force, hard reset) without + explicit request +- Never skip hooks unless explicitly requested + +## Planning + +When planning work: +- Highlight which steps can be done independently +- Consider forking subagents for concurrent work on independent steps +- Write implementation plans to `plans/IMPL<n>.md` if the project uses + this convention + +## Flake Structure + +The flake.nix follows ppad conventions: +- Uses ppad-nixpkgs as base +- Follows references to avoid duplication +- Supports LLVM backend via cabal flag +- Provides devShell with ghc, cabal, cc, llvm diff --git a/LICENSE b/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2025 Jared Tobin + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/bench/Main.hs b/bench/Main.hs @@ -0,0 +1,44 @@ +{-# OPTIONS_GHC -fno-warn-orphans #-} +{-# LANGUAGE BangPatterns #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE StandaloneDeriving #-} + +module Main where + +import Control.DeepSeq +import Criterion.Main +import GHC.Generics + +import Bitcoin.Prim.Tx +import Bitcoin.Prim.Tx.Sighash + +-- NFData instances ------------------------------------------------------------ + +deriving stock instance Generic TxId +instance NFData TxId + +deriving stock instance Generic OutPoint +instance NFData OutPoint + +deriving stock instance Generic TxIn +instance NFData TxIn + +deriving stock instance Generic TxOut +instance NFData TxOut + +deriving stock instance Generic Witness +instance NFData Witness + +deriving stock instance Generic Tx +instance NFData Tx + +deriving stock instance Generic SighashType +instance NFData SighashType + +-- benchmarks ------------------------------------------------------------------ + +main :: IO () +main = defaultMain [ + -- add benchmarks here + ] diff --git a/bench/Weight.hs b/bench/Weight.hs @@ -0,0 +1,43 @@ +{-# OPTIONS_GHC -fno-warn-orphans #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE StandaloneDeriving #-} + +module Main where + +import Control.DeepSeq +import GHC.Generics +import qualified Weigh as W + +import Bitcoin.Prim.Tx +import Bitcoin.Prim.Tx.Sighash + +-- NFData instances ------------------------------------------------------------ + +deriving stock instance Generic TxId +instance NFData TxId + +deriving stock instance Generic OutPoint +instance NFData OutPoint + +deriving stock instance Generic TxIn +instance NFData TxIn + +deriving stock instance Generic TxOut +instance NFData TxOut + +deriving stock instance Generic Witness +instance NFData Witness + +deriving stock instance Generic Tx +instance NFData Tx + +deriving stock instance Generic SighashType +instance NFData SighashType + +-- allocation benchmarks ------------------------------------------------------- + +main :: IO () +main = W.mainWith $ do + -- add allocation benchmarks here + pure () diff --git a/flake.nix b/flake.nix @@ -0,0 +1,92 @@ +{ + description = "Minimal Bitcoin transaction primitives for Haskell."; + + inputs = { + ppad-nixpkgs = { + type = "git"; + url = "git://git.ppad.tech/nixpkgs.git"; + ref = "master"; + }; + ppad-base16 = { + type = "git"; + url = "git://git.ppad.tech/base16.git"; + ref = "master"; + inputs.ppad-nixpkgs.follows = "ppad-nixpkgs"; + }; + ppad-sha256 = { + type = "git"; + url = "git://git.ppad.tech/sha256.git"; + ref = "master"; + inputs.ppad-nixpkgs.follows = "ppad-nixpkgs"; + }; + flake-utils.follows = "ppad-nixpkgs/flake-utils"; + nixpkgs.follows = "ppad-nixpkgs/nixpkgs"; + }; + + outputs = { self, nixpkgs, flake-utils, ppad-nixpkgs + , ppad-base16, ppad-sha256 + }: + flake-utils.lib.eachDefaultSystem (system: + let + lib = "ppad-tx"; + + pkgs = import nixpkgs { inherit system; }; + hlib = pkgs.haskell.lib; + llvm = pkgs.llvmPackages_19.llvm; + clang = pkgs.llvmPackages_19.clang; + + base16 = ppad-base16.packages.${system}.default; + base16-llvm = + hlib.addBuildTools + (hlib.enableCabalFlag base16 "llvm") + [ llvm clang ]; + + sha256 = ppad-sha256.packages.${system}.default; + sha256-llvm = + hlib.addBuildTools + (hlib.enableCabalFlag sha256 "llvm") + [ llvm clang ]; + + hpkgs = pkgs.haskell.packages.ghc910.extend (new: old: { + ppad-base16 = base16-llvm; + ppad-sha256 = sha256-llvm; + ${lib} = new.callCabal2nix lib ./. { + ppad-base16 = new.ppad-base16; + ppad-sha256 = new.ppad-sha256; + }; + }); + + cc = pkgs.stdenv.cc; + ghc = hpkgs.ghc; + cabal = hpkgs.cabal-install; + in + { + packages.default = hpkgs.${lib}; + + packages.haddock = hpkgs.${lib}.doc; + + devShells.default = hpkgs.shellFor { + packages = p: [ + (hlib.doBenchmark p.${lib}) + ]; + + buildInputs = [ + cabal + cc + llvm + ]; + + doBenchmark = true; + + shellHook = '' + PS1="[${lib}] \w$ " + echo "entering ${system} shell, using" + echo "cc: $(${cc}/bin/cc --version)" + echo "ghc: $(${ghc}/bin/ghc --version)" + echo "cabal: $(${cabal}/bin/cabal --version)" + echo "llc: $(${llvm}/bin/llc --version | head -2 | tail -1)" + ''; + }; + } + ); +} diff --git a/lib/Bitcoin/Prim/Tx.hs b/lib/Bitcoin/Prim/Tx.hs @@ -0,0 +1,108 @@ +{-# OPTIONS_HADDOCK prune #-} +{-# LANGUAGE BangPatterns #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE OverloadedStrings #-} + +-- | +-- Module: Bitcoin.Prim.Tx +-- Copyright: (c) 2025 Jared Tobin +-- License: MIT +-- Maintainer: Jared Tobin <jared@ppad.tech> +-- +-- Minimal Bitcoin transaction primitives, including raw transaction +-- types, serialisation to/from bytes, and txid computation. + +module Bitcoin.Prim.Tx ( + -- * Transaction Types + Tx(..) + , TxIn(..) + , TxOut(..) + , OutPoint(..) + , Witness(..) + , TxId(..) + + -- * Serialisation + , to_bytes + , from_bytes + , to_bytes_legacy + , to_base16 + , from_base16 + + -- * TxId + , txid + ) where + +import qualified Data.ByteString as BS +import qualified Data.ByteString.Base16 as B16 +import Data.Word (Word32, Word64) +import GHC.Generics (Generic) + +-- | Transaction ID (32 bytes, little-endian double-SHA256). +newtype TxId = TxId BS.ByteString + deriving (Eq, Show, Generic) + +-- | Transaction outpoint (txid + output index). +data OutPoint = OutPoint + { op_txid :: {-# UNPACK #-} !TxId + , op_vout :: {-# UNPACK #-} !Word32 + } deriving (Eq, Show, Generic) + +-- | Transaction input. +data TxIn = TxIn + { txin_prevout :: {-# UNPACK #-} !OutPoint + , txin_script_sig :: !BS.ByteString + , txin_sequence :: {-# UNPACK #-} !Word32 + } deriving (Eq, Show, Generic) + +-- | Transaction output. +data TxOut = TxOut + { txout_value :: {-# UNPACK #-} !Word64 -- ^ satoshis + , txout_script_pubkey :: !BS.ByteString + } deriving (Eq, Show, Generic) + +-- | Witness stack for a single input. +newtype Witness = Witness [BS.ByteString] + deriving (Eq, Show, Generic) + +-- | Complete transaction. +data Tx = Tx + { tx_version :: {-# UNPACK #-} !Word32 + , tx_inputs :: ![TxIn] + , tx_outputs :: ![TxOut] + , tx_witnesses :: ![Witness] -- ^ empty list for legacy tx + , tx_locktime :: {-# UNPACK #-} !Word32 + } deriving (Eq, Show, Generic) + +-- serialisation --------------------------------------------------------------- + +-- | Serialise a transaction to bytes. +-- +-- Uses segwit format if witnesses are present, legacy otherwise. +to_bytes :: Tx -> BS.ByteString +to_bytes = error "Bitcoin.Prim.Tx.to_bytes: not yet implemented" + +-- | Parse a transaction from bytes. +from_bytes :: BS.ByteString -> Maybe Tx +from_bytes = error "Bitcoin.Prim.Tx.from_bytes: not yet implemented" + +-- | Serialise a transaction to legacy format (no witness data). +-- +-- Used for txid computation. +to_bytes_legacy :: Tx -> BS.ByteString +to_bytes_legacy = error "Bitcoin.Prim.Tx.to_bytes_legacy: not yet implemented" + +-- | Serialise a transaction to base16. +to_base16 :: Tx -> BS.ByteString +to_base16 tx = B16.encode (to_bytes tx) + +-- | Parse a transaction from base16. +from_base16 :: BS.ByteString -> Maybe Tx +from_base16 b16 = do + bs <- B16.decode b16 + from_bytes bs + +-- txid ------------------------------------------------------------------------ + +-- | Compute the transaction ID (double SHA256 of legacy serialisation). +txid :: Tx -> TxId +txid = error "Bitcoin.Prim.Tx.txid: not yet implemented" diff --git a/lib/Bitcoin/Prim/Tx/Sighash.hs b/lib/Bitcoin/Prim/Tx/Sighash.hs @@ -0,0 +1,61 @@ +{-# OPTIONS_HADDOCK prune #-} +{-# LANGUAGE BangPatterns #-} +{-# LANGUAGE DeriveGeneric #-} + +-- | +-- Module: Bitcoin.Prim.Tx.Sighash +-- Copyright: (c) 2025 Jared Tobin +-- License: MIT +-- Maintainer: Jared Tobin <jared@ppad.tech> +-- +-- Sighash computation for legacy and BIP143 segwit transactions. + +module Bitcoin.Prim.Tx.Sighash ( + -- * Sighash Types + SighashType(..) + + -- * Legacy Sighash + , sighash_legacy + + -- * BIP143 Segwit Sighash + , sighash_segwit + ) where + +import Bitcoin.Prim.Tx (Tx) +import qualified Data.ByteString as BS +import Data.Word (Word64) +import GHC.Generics (Generic) + +-- | Sighash type flags. +data SighashType + = SIGHASH_ALL + | SIGHASH_NONE + | SIGHASH_SINGLE + | SIGHASH_ALL_ANYONECANPAY + | SIGHASH_NONE_ANYONECANPAY + | SIGHASH_SINGLE_ANYONECANPAY + deriving (Eq, Show, Generic) + +-- | Compute legacy sighash. +-- +-- Modifies a copy of the transaction based on sighash flags, appends +-- the sighash type as 4-byte little-endian, and double SHA256s. +sighash_legacy + :: Tx + -> Int -- ^ input index + -> BS.ByteString -- ^ scriptPubKey being spent + -> SighashType + -> BS.ByteString -- ^ 32-byte hash +sighash_legacy = error "Bitcoin.Prim.Tx.Sighash.sighash_legacy: not yet implemented" + +-- | Compute BIP143 segwit sighash. +-- +-- Required for signing segwit inputs. +sighash_segwit + :: Tx + -> Int -- ^ input index + -> BS.ByteString -- ^ scriptCode + -> Word64 -- ^ value being spent (satoshis) + -> SighashType + -> BS.ByteString -- ^ 32-byte hash +sighash_segwit = error "Bitcoin.Prim.Tx.Sighash.sighash_segwit: not yet implemented" diff --git a/ppad-tx.cabal b/ppad-tx.cabal @@ -0,0 +1,91 @@ +cabal-version: 3.0 +name: ppad-tx +version: 0.1.0 +synopsis: Minimal Bitcoin transaction primitives. +license: MIT +license-file: LICENSE +author: Jared Tobin +maintainer: jared@ppad.tech +category: Cryptography +build-type: Simple +tested-with: GHC == 9.10.3 +extra-doc-files: CHANGELOG +description: + Minimal Bitcoin transaction primitives for ppad libraries, including + raw transaction types, serialisation, txid computation, and sighash + calculation. + +flag llvm + description: Use GHC's LLVM backend. + default: False + manual: True + +source-repository head + type: git + location: git.ppad.tech/tx.git + +library + default-language: Haskell2010 + hs-source-dirs: lib + ghc-options: + -Wall + if flag(llvm) + ghc-options: -fllvm -O2 + exposed-modules: + Bitcoin.Prim.Tx + Bitcoin.Prim.Tx.Sighash + build-depends: + base >= 4.9 && < 5 + , bytestring >= 0.9 && < 0.13 + , ppad-base16 >= 0.2.1 && < 0.3 + , ppad-sha256 >= 0.3 && < 0.4 + +test-suite tx-tests + type: exitcode-stdio-1.0 + default-language: Haskell2010 + hs-source-dirs: test + main-is: Main.hs + + ghc-options: + -rtsopts -Wall + + build-depends: + base + , bytestring + , ppad-base16 + , ppad-tx + , tasty + , tasty-hunit + , tasty-quickcheck + +benchmark tx-bench + type: exitcode-stdio-1.0 + default-language: Haskell2010 + hs-source-dirs: bench + main-is: Main.hs + + ghc-options: + -rtsopts -O2 -Wall + + build-depends: + base + , bytestring + , criterion + , deepseq + , ppad-tx + +benchmark tx-weigh + type: exitcode-stdio-1.0 + default-language: Haskell2010 + hs-source-dirs: bench + main-is: Weight.hs + + ghc-options: + -rtsopts -O2 -Wall + + build-depends: + base + , bytestring + , deepseq + , ppad-tx + , weigh diff --git a/test/Main.hs b/test/Main.hs @@ -0,0 +1,27 @@ +{-# LANGUAGE OverloadedStrings #-} + +module Main where + +import Test.Tasty +import qualified Test.Tasty.HUnit as H + +-- main ------------------------------------------------------------------------ + +main :: IO () +main = defaultMain $ + testGroup "ppad-tx" [ + testGroup "serialisation" [ + testGroup "round-trip" [ + ] + , testGroup "known vectors" [ + ] + ] + , testGroup "txid" [ + ] + , testGroup "sighash" [ + testGroup "legacy" [ + ] + , testGroup "BIP143 segwit" [ + ] + ] + ]