Advanced Considerations
Why 10 Slots of ≤ 80 Bytes?
Default relay policy limits:
- Maximum 100 stack items for P2WSH.
- Maximum 80 bytes per non-script witness item.
- Maximum 3600 bytes for the witness script itself.
Ten slots provides headroom while keeping scripts simple (5 * OP_2DROP). You can scale by using multiple P2WDA inputs, keeping data only in the first P2WDA input and zeros in the rest.
Domain Separation (Recommended)
To harden against cross-protocol attacks, consider using domain separation:
message = Hash("P2WDA/v1" || txid || input_index || tx_signature || data)
data_signature = Schnorr.Sign(auth_private_key, message)This prevents signatures from being reused across different protocols or transactions.
Compression
Use a standard compression algorithm like DEFLATE to maximize data packing efficiency. Ensure your application layer can handle decompression and verify the integrity of the decompressed data.
Why SegWit Instead of Taproot?
A common question is why P2WDA uses SegWit's P2WSH instead of the newer Taproot technology. This decision is deliberate and based on fundamental economics of block space usage. Understanding this choice illuminates the elegant design of P2WDA.
The Block Space Reality
When people first hear about P2WDA, they might assume it should use Taproot since it's Bitcoin's newest upgrade. However, Taproot would actually consume more block space for our use case, making it less efficient. This counterintuitive reality stems from how these technologies were designed for different purposes.
Taproot offers two spending paths. The key path is remarkably efficient, requiring only a 64-byte Schnorr signature, but it cannot carry arbitrary data. To include data, you must use the script path, which requires a control block containing the internal public key, parity information, and Merkle proof of your script's inclusion in the taproot tree. Even with the simplest possible tree structure, this control block adds approximately 65 bytes of pure overhead.
Let's examine the concrete numbers for storing 500 bytes of authenticated data:
With P2WSH (what P2WDA uses), the witness contains the transaction signature (~72 bytes), your data (500 bytes), and the witness script (~40 bytes), totaling approximately 612 bytes, which equals 612 weight units.
With Taproot's script path, you would need a Schnorr signature (64 bytes), your data (500 bytes), the tapscript (~40 bytes), and the control block (~65 bytes), totaling approximately 669 bytes, which equals 669 weight units.
This represents about 10% more block space consumption for identical functionality. When your goal is cost-efficient data storage, every byte matters, and this overhead directly translates to higher fees for users.
Future Extensions
- Use annexes (BIP490) to carry larger payloads if needed and stop requiring another signature in the witness stack.
- Explore multi-signature variants for collaborative data signing.