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 / Oblivous_Nostr_Relays.md
Created October 22, 2025 16:03
Oblivous Nostr Relays

Nostr-Native Oblivious Nostr Relay (ONR)

Introduction

Nostr is a distributed publish-subscribe protocol in which clients publish signed events (“notes”) and subscribe to others’ events using filters. Relays act as lightweight store-and-forward servers that index, persist, and broadcast events to connected subscribers. However, because Nostr connections are typically made directly over WebSocket, clients expose their IP addresses to relays, allowing for potential metadata correlation.

The proposed Oblivious Nostr Relay (ONR) design introduces a privacy-preserving gateway that forwards encrypted client requests to a target relay without revealing the client’s network identity. Functionally, the ONR acts as an application-layer proxy analogous to an Oblivious HTTP (OHTTP) relay, but implemented using Nostr primitives

Protocol

@arminsabouri
arminsabouri / Privacy Preserving Nostr + BIP 77.md
Last active September 7, 2025 15:33
Dev notes: Privacy Preserving Nostr + BIP-77

Privacy preserving Nostr Relays and BIP-77

Nostr is a pub/sub protocol: clients publish signed events (notes) and subscribe to other's events using filters. Relays are lean store-and-forward servers that persist and index events and push them to connected subscribers. When a client connects to a relay, it reveals its IP address, enabling metadata correlation.

How can we:

  1. Prevent a relay from learning a client’s network identity while they interact with Nostr.
  2. Enable interactive protocols to message over Nostr s.t the messages are indistinguishable from ordinary nostr noise.

Nostr Relays as OHTTP Gateways

@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 armin@team.casa Jameson Lopp jameson@team.casa Justin Moore justin@unchained.com 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()