Skip to content

Instantly share code, notes, and snippets.

View arminsabouri's full-sized avatar
🎯
Focusing

Armin Sabouri arminsabouri

🎯
Focusing
View GitHub Profile
@arminsabouri
arminsabouri / statement.md
Created June 30, 2025 20:27
Wallet fingerprint statement

A core part of Bitcoin’s pseudonymity is making sure on-chain surveillance can’t infer anything about transaction participants beyond what’s already visible on chain. Wallet fingerprints violate this by leaking additional identifying details. Once an observer knows which wallet created a transaction, they can combine that with other heuristics such as, change output patterns or common input ownership to cluster addresses and glean other details. These heuristics weaken the privacy guarantees of Bitcoin and undermine existing privacy protocols.

Researchers have already identified multiple wallet fingerprints in existing wallets (0, 1). But discovering these fingerprints manually is laborious and requires deep familiarity with the wallet’s internal logic.

Our project automates the detection and storage of wallet fingerprints using a Retrieval-Augment

@arminsabouri
arminsabouri / Liana_Payjoin_Integration.md
Last active April 2, 2025 23:29
Liana Payjoin Integration

Payjoin Liana Integration

Getting Dev Env Setup

Get regtest setup locally. I use user:pass creds. Cookies work too. For this guide I will assume you are using default ports.

Gui

  1. cd liana-gui
  2. cargo run
  3. For network, be sure to select regtest
@arminsabouri
arminsabouri / CSFS_CAT.md
Last active October 7, 2024 17:43
Emulating CSFS using CAT

Emulating Check Sig From Stack (OP_CSFS) using OP_CAT

OP_CAT enables the construction of covenants within Bitcoin script, albeit in a somewhat hacky manner. It requires the spender to place transaction elements on the stack, concatenate all the transaction elements, and then trick OP_CHECKSIG into verifying these elements. The spender accomplishes this by using a signature where both the private key and private nonce are set to 1.

I refere to this hack as the Poelstra trick and you can find more information here Understanding the Poelstra trick is the hard part of learning how to build a variant CSFS.

Some Background

Elements Project's OP_CHECKSIGFROMSTACK (CSFS) verifies an ECDSA signature sig over an arbitrary message m against a public key pk. Unlike Bitcoin's existing signature-checking opcodes, such as OP_CHECKSIG, which derive the message from the transaction executing the opcode, OP_CHECKSIGFROMSTACK reads an arbitrar

@arminsabouri
arminsabouri / fish.bash
Created January 27, 2024 01:22
Find White spaces introduced in git commits using fish shell
for commit in (git log --format='%H' HEAD~5..HEAD)
git show $commit | sed 's/.. $/& <<<< HERE/'
echo "====="
end | less
@arminsabouri
arminsabouri / ZKCP-2WP.md
Last active October 13, 2023 13:45
Zero-Knowledge Contingent Payment Two Way Peg

The foundation of this protocol hinges on Zero Knowledge Proofs (ZKPs), which encompass a diverse array of systems and types.

In essence, a zero-knowledge proof (ZKP) for general computation is a cryptographic framework that empowers an individual to execute an arbitrary program, using a combination of publicly accessible and confidential inputs, and convincingly demonstrate to others that the program accepted these inputs, all without divulging any additional information about its operations or the concealed inputs.

Provided we assume that a ZKP system exists and that a buyer (an entity seeking to initiate a peg-in) and a seller (a node aiding the buyer in pegging in) can engage in secure, authenticated communication, then we can construct a trustless atomic peg to a sidechain.

Key Assumptions:

  1. The existence of a ZKP black box.
  2. The sidechain possesses the capability to perform introspection on transactions and its own blockchain.
  3. The buyer (referred to as "B") and the seller (referred to as "S")

BIP: BIP-unhardened-multisig Title: Unhardened Derivation Paths for Multisignature Coordination Author: Armin Sabouri [email protected] Jameson Lopp [email protected] Justin Moore [email protected] Status: Draft Type: Informational Created: 2023-01-03 License: BSD-2-Clause

@arminsabouri
arminsabouri / error_status_words.md
Last active March 21, 2023 14:27
Common Ledger Error Codes
  • 0x6982 = "Status word for command not valid for security reasons (for example: device needs to be unlocked with PIN)."
  • 0x6985 = "Status word for denied by user."
  • 0x6A80 = "Status word for incorrect data."
  • 0x6A82 = "Status word for request not currently supported (but not otherwise wrong)."
  • 0x6A87 = "Status word for incorrect data length"
  • 0x6D00 = "Status word for unknown command with this INS."
  • 0x6E00 = "Status word for instruction class is different than CLA."
  • 0xB000 = "Status word for wrong response length (buffer too small or too big)."
  • 0xB007 = "Status word for bad device state."
  • 0xB008 = "Status word for signature fail."
@arminsabouri
arminsabouri / README.md
Last active June 4, 2023 02:07
Ledger 2.1.0 Psbtv2 Conversion

LedgerHQ has laid the foundation for a PSBTv2 library, but it currently lacks some features and has issues with de/serialization. A complete Psbtv2 class can be found in my fork.

It is suggested to use PSBTv0 for all operations and only convert to v2 when communicating with the Ledger device. This can be achieved through utilizing BitcoinJS's excellent PSBTv0 library and utilizing an adapter function from v0 -> v2.

For exmaple if your're working with p2sh(p2wsh) script types, you might have something like:

export function convertPsbtv0ToV2(psbtv0: Psbt): PsbtV2 {
  const psbtv2 = new PsbtV2()

Start by using nix

Run nix-shell in the root directory

Start the virtual env using poetry shell

Run poetry shell in the root directory

We'll be building and running the core firmware

cd core make build_unix

Run the emulator

./emu.py If you are making changes to any python source code you shouldn't have to run the make command again.

@arminsabouri
arminsabouri / main.py
Last active November 17, 2022 21:15
Parse Xpub Components
def to_hd_node(base58DecodedXpub):
try:
return {
'version': base58DecodedXpub[0:8],
'depth': base58DecodedXpub[8:10],
'pfp': base58DecodedXpub[10:18],
'index': base58DecodedXpub[18:26],
'chaincode': base58DecodedXpub[26:90],
'key': base58DecodedXpub[90:156],
'checksum': base58DecodedXpub[156:164]