Unofficial embit fork carrying the unified opt-in signature hash defined by Bitcoin Knots. Not audited.
  • Python 99.7%
  • Makefile 0.2%
  • C 0.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Kyle 🐆 5f700aa322
Take the committed script type from the script, not from which PSBT fields are set (#2)
The unified message commits a byte naming the script type, which domain
separates the four so a signature made for one can never verify as another.
It was derived from field presence: witness_script or witness_utxo being set
meant WITNESS_V0.

BIP174 allows a legacy input to be carried as witness_utxo, and consensus can
only read that output as BARE. So the same P2PKH UTXO committed WITNESS_V0
through one carrier and BARE through the other, one of the two signatures could
not verify on chain, and two signers given different carriers of one PSBT
disagreed. It also broke multisig interop with the other implementations, which
all classify from the spent scriptPubKey.

Classified from the script now, in both PSBT and PSBTView. The legacy digest
selection is untouched: it is upstream's, and only the unified message commits
the byte to consensus.
2026-09-04 14:51:32 -04:00
.github/workflows ci: run the unit tests on this fork branch 2026-08-27 10:30:22 -04:00
docs add support for signing with descriptor and descriptor keys 2022-06-01 12:58:35 +02:00
examples use black, pyproject.toml, pytest, mypy 2023-08-05 23:01:42 +02:00
secp256k1 libsecp256k1 binary for M1 Macs (darwin_arm64) (#29) 2022-06-24 13:48:21 +02:00
src/embit Take the committed script type from the script, not from which PSBT fields are set (#2) 2026-09-04 14:51:32 -04:00
tests Take the committed script type from the script, not from which PSBT fields are set (#2) 2026-09-04 14:51:32 -04:00
.gitignore add .idea to .gitignore (#46) 2023-06-03 18:43:54 +02:00
.gitmodules Add a secp256k1 makefile and building instructions (#24) 2022-01-17 11:12:57 +01:00
.pre-commit-config.yaml use black, pyproject.toml, pytest, mypy 2023-08-05 23:01:42 +02:00
LICENSE bump version 2022-10-16 15:59:57 +02:00
pyproject.toml bump version 2024-05-30 12:43:09 +02:00
README.md README: say what this fork is before upstream's documentation 2026-09-03 16:10:29 -04:00
setup.py use black, pyproject.toml, pytest, mypy 2023-08-05 23:01:42 +02:00

embit, with the unified opt-in signature hash

An unofficial fork of embit carrying the unified opt-in signature hash defined by the Bitcoin hardfork, as Bitcoin Knots v29.4.1.knots20260508 specifies it in doc/unified-sighash.md. It is not affiliated with the embit authors, and it is not audited. The MIT licence it inherits disclaims all warranty, and that applies here as much as upstream.

Adds Transaction.sighash_unified() and the streaming PSBTView.sighash_unified(), hash type negotiation in sign_with(), and SIGHASH.UNIFIED. Signing that does not set the opt-in bit is byte-identical to upstream. Liquid refuses the bit.

This branch is based on the v0.8.0 release, which is what downstream builds pin. The same work rebased onto upstream master is on upstream-pr/unified-sighash.

Everything below the divider is upstream's documentation.


embit

A minimal bitcoin library for MicroPython and Python3 with a focus on embedded systems.

Should remain minimal to fit in a microcontroller. Also easy to audit.

Examples can be found in examples/ folder.

Documentation: https://embit.rocks/

Support the project: bc1qd4flfrxjctls9ya244u39hd67pcprhvka723gv

Requirements

MicroPython

Requires a custom MicroPython build with extended hashlib module and secp256k1 bindings.

To install copy the content of embit folder to the board. To save some space you can remove files embit/util/ctypes_secp256k1.py and embit/util/pyhashlib.py - they are used only in Python3.

Python 3

To install run pip3 install embit.

To install in development mode (editable) clone and run pip3 install -e . from the root folder.

PyPi installation includes prebuilt libraries for common platforms (win, macos, linux, raspi) - see src/embit/util/prebuilt/ folder. Library is built from libsecp-zkp fork for Liquid support, but will work with pure libsecp256k1 as well - just Liquid functionality doesn't work. If it fails to use the prebuilt or system library it will fallback to pure python implementation.

If you want to build the lib yourself, see: Building secp256k1 for embit.

Using non-English BIP39 wordlists

BIP39 defines wordlists for:

  • English
  • Japanese
  • Korean
  • Spanish
  • Chinese (Simplified)
  • Chinese (Traditional)
  • French
  • Italian
  • Czech
  • Portuguese

embit assumes English and does not include the other wordlists in order to keep this as slim as possible.

However, you can override this default by providing an alternate wordlist to any of the mnemonic-handling methods:

spanish_wordlist = [
    "ábaco",
    "abdomen",
    "abeja",
    "abierto",
    "abogado",
    "abono",
    "aborto",
    "abrazo",
    "abrir",
    "abuelo",
    ...
]

mnemonic_is_valid(mnemonic, wordlist=spanish_wordlist)
mnemonic_to_seed(mnemonic, wordlist=spanish_wordlist)
mnemonic_to_bytes(mnemonic, wordlist=spanish_wordlist)
mnemonic_from_bytes(bytes_data, wordlist=spanish_wordlist)

Development

Install in developer mode with dev dependencies:

pip install -e .[dev]

Install pre-commit hook:

pre-commit install

Run tests with desktop python:

pytest

Run tests with micropython:

cd tests
micropython ./run_tests.py