Libauth 3.0.0

repository·master·Indexed 43 days ago

https://github.com/bitauth/libauth

An ultra-lightweight JavaScript library for Bitcoin Cash, Bitcoin, and Bitauth applications. Designed for portability across Node.js, Deno, and browsers, it provides a functional API for address formats (Base58, Bech32, CashAddress), cryptographic operations (secp256k1, SHA, RIPEMD), BIP32/BIP39 key management, P2P message decoding, and Virtual Machine (VM) execution including CashAssembly support.

Tokens
35.6K
Snippets
101
Records
145
Agent score
55%

What's inside Libauth

  1. Overview of Libauth API capabilities

    master

    Libauth provides a comprehensive suite of low-level and high-level utilities for blockchain development, specifically focused on Bitcoin and Bitcoin Cash ecosystems. High-level utilities are composed from lower-level primitives, allowing developers to remix behavior with minimal maintenance.

    The API is organized into several functional domains:

    • Address Formats: Encoding and decoding for Base58, Bech32, CashAddress, and related formats.
    • Crypto: Hashing (SHA, RIPEMD), HMAC, PBKDF2, and secp256k1 operations.
    • Formats: Conversions between Base-N, Base64, Binary Strings, Hex, and various numeric representations (including CompactUint/VarInt and Satoshi values).
    • Keys: BIP32 (HD Keys), BIP39 (Mnemonics), WIF, and general key generation/validation.
    • P2P Messages: Utilities for decoding P2P messages, handling transactions, and calculating dust thresholds.
    • Virtual Machines: Built-in VMs for different instruction sets (BCH, XEC, etc.), debugging tools (assembler/disassembler), and operation combinators.
    • Wallet Engine: Advanced features including Bitcoin Cash Metadata Registries (BCMRs), CashAssembly language/compiler, multi-party compilation, and wallet templates.
  2. How Libauth works: Functional Design

    master

    Libauth is designed around a functional programming model rather than a single, overarching, object-oriented API. This design provides several benefits:

    • Flexibility: Complex functionality is composed of simpler functions, allowing you to remix or tweak methods without forking the library.
    • Smaller application bundles: Because functionality is composed of individual functions, you can import only what you need, enabling effective dead-code elimination (tree-shaking).
    • Better auditability: Smaller functions and a lack of dependencies make it easier to audit critical code.
    • Full portability: The library avoids platform-specific APIs, ensuring the same code paths run across all JavaScript environments (Node.js, Deno, and browsers).
  3. How Libauth handles errors

    master

    In Libauth, runtime errors that are expected in production applications are typically returned as strings rather than being thrown as Error objects. This approach ensures type safety, consistency across environments, and avoids exposing internal details like stack traces.

    When a function returns a result that could be an error, the return type is usually a union of the successful result type and string. To handle this, you should check if the result is a string before proceeding with the successful data.

  4. Work with Hierarchical Deterministic (HD) Keys

    master

    Libauth provides utilities for managing BIP32-compliant Hierarchical Deterministic (HD) keys. HD keys allow you to generate a structured tree of keys from a single master key.

    Key capabilities include:

    • Derivation: Create sub-accounts or specific child keys using paths (e.g., deriveHdPath, deriveHdPathRelative).
    • Encoding/Decoding: Convert between raw nodes and string formats like extended private keys (xprv) and extended public keys (xpub) using encodeHdPrivateKey, decodeHdPrivateKey, encodeHdPublicKey, and decodeHdPublicKey.
    • Identification: Generate identifiers for nodes using hdPrivateKeyToIdentifier or hdPublicKeyToIdentifier.
    • Security: Use crackHdPrivateNodeFromHdPublicNodeAndChildPrivateNode to understand the risk where gaining a single non-hardened child private key allows an attacker to derive the parent private key if they also possess the parent extended public key.
  5. Use Standard vs. Non-Standard VM modes for testing

    master

    When implementing or testing a VM, you must account for two modes of operation:

    1. standard mode: The strictest mode. Use this for applications validating transactions before relaying them over a P2P network. A transaction must pass in this mode to be considered valid for general network propagation.
    2. non-standard mode: A more lax mode used primarily for validating newly mined blocks. Transactions valid in standard mode are always valid in non-standard mode, but non-standard mode allows transactions that would be rejected by the standard rules.

    This distinction prevents resource-exhaustion attacks where malicious actors attempt to relay complex, slow-to-validate transactions that could disrupt miners.

  6. Multi-party transaction compilation with Libauth

    master

    Libauth supports advanced multi-party wallet creation and transaction compilation (e.g., 2-of-2 or 2-of-3 multisig).

    Warning: These APIs are low-level and generalized. Safe usage in multi-party applications requires a deep understanding of the security risks and the compiler infrastructure.

    Core Workflow Functions:

    • generateTransaction: Generates a transaction.
    • extractMissingVariables: Identifies variables needed to complete a transaction.
    • extractResolvedVariables: Identifies variables already present in the compilation data.
    • safelyExtendCompilationData: Extends existing compilation data with new information.

    For implementation patterns, refer to the end-to-end tests in the source repository, specifically transaction-e2e.2-of-2-recoverable.spec.ts for vault recovery scenarios.

  7. How Libauth handles instruction sets and VM support

    master

    Libauth provides support for Virtual Machines (VMs) used by public bitcoin-like networks and stable upgrade proposals.

    Key Principles:

    • VM Selection: When multiple VMs share similar functionality, Libauth's exported utilities prefer the configuration used by the latest version of the Bitcoin Cash (BCH) VM.
    • Upgrade Handling: For pending BCH upgrades with wide consensus and established activation dates, Libauth may upgrade utilities before mainnet activation. In the event of a network split, Libauth attempts to support both sides and may delay selecting a default VM until the split is resolved.
    • Deprecation Policy: Libauth generally only maintains support for active VM versions. When an upgrade replaces a previous version without a network split (e.g., BCH_2019_05 being replaced by BCH_2019_11), the older version's specific code paths and flags are removed to maintain code simplicity.
  8. Understand Libauth VMB Test Vectors

    master

    Libauth uses Virtual Machine Bytecode (VMB) test vectors to ensure cross-implementation compatibility for supported Bitcoin-like networks. Unlike traditional script tests that only test bytecode, VMB tests validate the entire transaction validation infrastructure. Each test vector includes a complete transaction and the specific UTXOs required for verification.

    Each test in a VMB array contains:

    • A unique identifier (hash-based).
    • A description of the test purpose.
    • The disassembled (human-readable) unlocking script.
    • The disassembled locking script.
    • The full, encoded test transaction.
    • An encoded list of UTXOs (ordered to match the transaction inputs).
  9. Understand Libauth VMB Tests

    master
    Libauth includes a test suite containing cross-implementation Virtual Machine Bytecode (VMB) test vectors. These vectors are provided for each supported Virtual Machine to ensure consistency across different implementations. For detailed information on how these tests are structured and used, refer to the dedicated VMB Tests documentation.
  10. Handle Error Correction in CashAddress Formats

    master

    CashAddress-like formats support correcting up to 2 errors using attemptCashAddressFormatErrorCorrection.

    CAUTION: Error correction is not fail-safe. If a payload has more than 2 errors, it might be 'corrected' to an incorrect but plausible payload. Never use naive error correction for irreversible actions like sending payments.

    For high-stakes data (like secret keys), use a safe failure mode where you prompt the user to review the errors rather than automatically applying the correction.

    import { attemptCashAddressFormatErrorCorrection } from '@bitauth/libauth';
    
    const maybeAddress = 'bch-est:qq2azmyyv6dtgczexyalqar70q036yund53jvfde0z';
    const result = attemptCashAddressFormatErrorCorrection(maybeAddress);
    
    if (typeof result === 'string') {
      // result is an error message describing where the errors are
      console.error(result);
      return;
    }
    
    // result.address contains the corrected address
    // result.corrections contains the indices of the corrected characters
  11. Verify Bitcoin Cash transactions

    master

    To verify a transaction using Bitcoin Cash's latest standard VM, use createVirtualMachineBCH with the standard parameter set to true.

    1. Create the VM instance using createVirtualMachineBCH(true).
    2. Decode the transaction using decodeTransaction.
    3. Decode the source outputs (UTXOs) using decodeTransactionOutputs.
    4. Call vm.verify({ sourceOutputs, transaction }).

    The verify method returns true if successful, or a string containing the error message if verification fails.

    import {
      assertSuccess,
      decodeTransaction,
      decodeTransactionOutputs,
      createVirtualMachineBCH,
    } from '@bitauth/libauth';
    
    const vm = createVirtualMachineBCH(true);
    
    /* Decode the transaction, throwing any errors */
    const transaction = assertSuccess(decodeTransaction(vmbTest.tx));
    /* Decode the serialized outputs, throwing any errors */
    const sourceOutputs = assertSuccess(decodeTransactionOutputs(vmbTest.utxos));
    
    // Result is either `true` or an error message (`string`)
    const result = vm.verify({ sourceOutputs, transaction });
    
    if (typeof result === 'string') {
      console.error(result);
    } else {
      console.log('Transaction verified 🚀');
    }