adimiuprix/taproot-php

Bitcoin Taproot implementation for PHP using secp256k1

Maintainers

Package info

github.com/adimiuprix/bitroot-php

pkg:composer/adimiuprix/taproot-php

Transparency log

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

dev-main 2026-08-17 12:48 UTC

This package is auto-updated.

Last update: 2026-08-17 12:50:34 UTC


README

Bitcoin Taproot implementation for PHP using secp256k1 extension.

Features

  • Secp256k1 Integration: Native PHP extension wrapper for cryptographic operations
  • Schnorr Signatures: BIP340 Schnorr signature implementation
  • Taproot Addresses: Generate and validate P2TR (Pay-to-Taproot) addresses
  • Script Trees: Build and manage Taproot script trees (MAST)
  • Key Tweaking: Support for key aggregation and tweaking

Requirements

  • PHP >= 8.5
  • GMP extension
  • kornrunner/secp256k1 library
  • fenguoz/bip39-mnemonic-php library

Installation

Install via Composer:

composer require bitroot/taproot-php

Or add to your composer.json:

{
    "require": {
        "bitroot/taproot-php": "^1.0"
    }
}

Then run:

composer install

Quick Start

See example.php for a complete single-file demonstration:

php example.php

Or try this quick snippet:

<?php

require_once 'vendor/autoload.php';

use Bitroot\Bitcoin\Secp256k1;
use Bitroot\Bitcoin\Taproot;
use Bitroot\Bitcoin\Address;

// Generate key pair
$secp = new Secp256k1();
$privateKey = $secp->generatePrivateKey();
$publicKey = $secp->getXOnlyPublicKey($privateKey);

// Create Taproot address
$taproot = new Taproot();
$output = $taproot->createKeyPathSpend($publicKey);
$address = Address::fromTaprootOutput($output);

echo "Your Taproot Address: " . $address;
// Output: bc1p...

Usage

1. BIP39 Mnemonic Seed Phrases

Generate and use mnemonic seed phrases (BIP39):

use Bitroot\Bitcoin\Mnemonic;

$mnemonic = new Mnemonic('en'); // English language

// Generate 24-word mnemonic (256-bit entropy)
$seedPhrase = $mnemonic->generate(256);
echo $seedPhrase;
// abandon abandon abandon ... art

// Generate with specific word count
$seedPhrase12 = $mnemonic->generateWithWordCount(12);
$seedPhrase24 = $mnemonic->generateWithWordCount(24);

// Validate mnemonic
$isValid = $mnemonic->validate($seedPhrase);

// Derive master private key
$masterKey = $mnemonic->toMasterKey($seedPhrase);

// With optional passphrase for additional security
$masterKey = $mnemonic->toMasterKey($seedPhrase, 'my-passphrase');

// Convert to/from entropy
$entropy = $mnemonic->toEntropy($seedPhrase);
$seedPhrase = $mnemonic->fromEntropy($entropy);

2. Generate Private/Public Key Pair

use Bitroot\Bitcoin\Secp256k1;

$secp = new Secp256k1();

// Generate new private key
$privateKey = $secp->generatePrivateKey();

// Derive public key
$publicKey = $secp->getPublicKey($privateKey);

echo "Private Key: " . bin2hex($privateKey) . "\n";
echo "Public Key: " . bin2hex($publicKey) . "\n";

3. Schnorr Signatures (BIP340)

use Bitroot\Bitcoin\Schnorr;

$schnorr = new Schnorr();

$privateKey = hex2bin('your_private_key_hex');
$message = hash('sha256', 'Hello Bitcoin', true);

// Sign message
$signature = $schnorr->sign($message, $privateKey);

// Verify signature
$publicKey = $secp->getPublicKey($privateKey);
$isValid = $schnorr->verify($signature, $message, $publicKey);

echo "Signature: " . bin2hex($signature) . "\n";
echo "Valid: " . ($isValid ? 'Yes' : 'No') . "\n";

4. Taproot Address Generation

use Bitroot\Bitcoin\Taproot;
use Bitroot\Bitcoin\Address;

$taproot = new Taproot();

// Key-path spending (simple P2TR)
$internalKey = $secp->getPublicKey($privateKey);
$taprootOutput = $taproot->createKeyPathSpend($internalKey);

// Generate address (mainnet)
$address = Address::fromTaprootOutput($taprootOutput, 'mainnet');
echo "Taproot Address: " . $address . "\n"; // bc1p...

// Testnet
$addressTestnet = Address::fromTaprootOutput($taprootOutput, 'testnet');
echo "Testnet Address: " . $addressTestnet . "\n"; // tb1p...

5. Script Tree (MAST)

use Bitroot\Bitcoin\Taproot;
use Bitroot\Bitcoin\Script;

$taproot = new Taproot();

// Create script leaves
$script1 = Script::fromAsm('OP_CHECKSIG');
$script2 = Script::fromAsm('144 OP_CHECKSEQUENCEVERIFY OP_DROP OP_CHECKSIG');

// Build script tree
$scriptTree = $taproot->buildScriptTree([
    $script1,
    $script2
]);

// Create Taproot output with script tree
$internalKey = $secp->getPublicKey($privateKey);
$taprootOutput = $taproot->createScriptPathSpend($internalKey, $scriptTree);

// Generate address
$address = Address::fromTaprootOutput($taprootOutput);
echo "Taproot Script Address: " . $address . "\n";

// Get control block for spending
$controlBlock = $taproot->getControlBlock($scriptTree, 0); // For first script

6. Key Tweaking

use Bitroot\Bitcoin\Taproot;

$taproot = new Taproot();

$internalKey = $secp->getPublicKey($privateKey);
$tweak = hash('sha256', 'some_tweak_data', true);

// Tweak public key
$tweakedKey = $taproot->tweakPublicKey($internalKey, $tweak);

echo "Original: " . bin2hex($internalKey) . "\n";
echo "Tweaked: " . bin2hex($tweakedKey) . "\n";

7. Complete Example from Mnemonic to Address

<?php

require_once 'vendor/autoload.php';

use Bitroot\Bitcoin\Mnemonic;
use Bitroot\Bitcoin\Secp256k1;
use Bitroot\Bitcoin\Schnorr;
use Bitroot\Bitcoin\Taproot;
use Bitroot\Bitcoin\Address;

// Step 1: Generate mnemonic
$mnemonic = new Mnemonic('en');
$seedPhrase = $mnemonic->generate(256); // 24 words
echo "Seed Phrase: " . $seedPhrase . "\n\n";

// Step 2: Derive master key
$masterKey = $mnemonic->toMasterKey($seedPhrase);
echo "Master Key: " . bin2hex($masterKey) . "\n\n";

// Step 3: Generate key pair
$secp = new Secp256k1();
$publicKey = $secp->getXOnlyPublicKey($masterKey);
echo "Public Key: " . bin2hex($publicKey) . "\n\n";

// Step 4: Create Taproot address
$taproot = new Taproot();
$taprootOutput = $taproot->createKeyPathSpend($publicKey);
$address = Address::fromTaprootOutput($taprootOutput, 'mainnet');
echo "Taproot Address: " . $address . "\n\n";

// Step 5: Sign message with Schnorr
$schnorr = new Schnorr();
$message = hash('sha256', 'Hello Taproot!', true);
$signature = $schnorr->sign($message, $masterKey);
$isValid = $schnorr->verify($signature, $message, $publicKey);

echo "Signature: " . bin2hex($signature) . "\n";
echo "Valid: " . ($isValid ? 'Yes' : 'No') . "\n";

Examples

Single comprehensive example demonstrating all features:

# Run the complete example
composer run examples
# or
php examples/all-features.php

The example demonstrates:

  • ✓ BIP39 Mnemonic (24 & 12 words)
  • ✓ Key Generation (Private, Public, X-Only)
  • ✓ Taproot Addresses (Mainnet & Testnet)
  • ✓ Schnorr Signatures (BIP340)
  • ✓ Script Trees (MAST) with multiple spending paths
  • ✓ Control Blocks for script-path spending
  • ✓ Wallet Recovery from mnemonic

Output: Clean, organized display with all features in ~150 lines of code.

API Reference

Mnemonic Class

  • generate(int $strength = 256): string - Generate mnemonic (128, 160, 192, 224, 256 bits)
  • generateWithWordCount(int $wordCount): string - Generate with specific word count (12, 15, 18, 21, 24)
  • validate(string $mnemonic): bool - Validate mnemonic phrase
  • toSeed(string $mnemonic, string $passphrase = ''): string - Convert to 64-byte seed
  • toMasterKey(string $mnemonic, string $passphrase = ''): string - Derive master private key (BIP32)
  • fromEntropy(string $entropy): string - Create mnemonic from entropy
  • toEntropy(string $mnemonic): string - Extract entropy from mnemonic
  • getWordCount(string $mnemonic): int - Count words in mnemonic

Secp256k1 Class

  • generatePrivateKey(): string - Generate random 32-byte private key
  • getPublicKey(string $privateKey, bool $compressed = true): string - Derive public key from private key
  • getXOnlyPublicKey(string $privateKey): string - Get 32-byte X-only public key for Taproot
  • validatePrivateKey(string $privateKey): bool - Validate private key
  • validatePublicKey(string $publicKey): bool - Validate public key
  • privateKeyTweakAdd(string $privateKey, string $tweak): string - Tweak private key
  • publicKeyTweakAdd(string $publicKey, string $tweak): string - Tweak public key
  • sign(string $message, string $privateKey): string - Sign with ECDSA
  • verify(string $signature, string $message, string $publicKey): bool - Verify ECDSA signature

Schnorr Class

  • sign(string $message, string $privateKey, ?string $auxRand = null): string - Sign message with Schnorr
  • verify(string $signature, string $message, string $publicKey): bool - Verify Schnorr signature

Taproot Class

  • createKeyPathSpend(string $internalKey): array - Create key-path only Taproot output
  • createScriptPathSpend(string $internalKey, array $scriptTree): array - Create Taproot with script tree
  • buildScriptTree(array $scripts): array - Build Merkle tree from scripts
  • tweakPublicKey(string $publicKey, string $tweak): string - Tweak public key
  • getControlBlock(array $scriptTree, int $leafIndex): string - Get control block for script spending

Address Class

  • fromTaprootOutput(array $output, string $network = 'mainnet'): string - Generate Bech32m address from Taproot output
  • decode(string $address): array - Decode Bech32m address
  • validate(string $address, ?string $network = null): bool - Validate Taproot address

Script Class

  • fromAsm(string $asm): string - Create script from ASM notation
  • toAsm(string $script): string - Convert script to ASM notation
  • pushData(string $data): string - Push data to script
  • encodeNumber(int $num): string - Encode number for script

Technical Details

This library implements:

  • BIP39: Mnemonic code for generating deterministic keys
  • BIP32: Hierarchical Deterministic Wallets (master key derivation)
  • BIP340: Schnorr Signatures for secp256k1
  • BIP341: Taproot: SegWit version 1 spending rules
  • BIP342: Validation of Taproot Scripts
  • Bech32m: Address encoding for Taproot

Testing

composer install
./vendor/bin/phpunit

Security

This library is intended for educational and development purposes. For production use:

  • Always use hardware wallets for key management
  • Never expose private keys
  • Audit your code thoroughly
  • Use testnet for testing

License

MIT License. See LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Dependencies

Resources