<oembed><type>rich</type><version>1.0</version><author_name>npub19r53ufymeycp9wzk3yzru55y5u46e4vva2lj7nak4zrn6yhrna7qsyj32s</author_name><author_url>https://nostr.ae/npub19r53ufymeycp9wzk3yzru55y5u46e4vva2lj7nak4zrn6yhrna7qsyj32s</author_url><provider_name>njump</provider_name><provider_url>https://nostr.ae</provider_url><html>📅 Original date posted:2020-09-18&#xA;📝 Original message:Conceptually this is so simple and explicit it almost seems like an obvious&#xA;primitive.&#xA;&#xA;Glossing over some of the design/policy decisions...&#xA;&#xA;I wonder what the real-world privacy implications are due to the&#xA;dependencies now being encoded on-chain rather than requiring some effort&#xA;to watch the mempool?&#xA;&#xA;Cory&#xA;&#xA;On Fri, Sep 18, 2020, 20:52 Jeremy via bitcoin-dev &lt;&#xA;bitcoin-dev at lists.linuxfoundation.org&gt; wrote:&#xA;&#xA;&gt; Hi Bitcoin Devs,&#xA;&gt;&#xA;&gt;&#xA;&gt; I&#39;d like to share with you a draft proposal for a mechanism to replace CPFP and RBF for&#xA;&gt; increasing fees on transactions in the mempool that should be more robust against attacks.&#xA;&gt;&#xA;&gt; A reference implementation demonstrating these rules is available&#xA;&gt; [here](https://github.com/bitcoin/bitcoin/compare/master...JeremyRubin:subsidy-tx) for those who&#xA;&gt; prefer to not read specs.&#xA;&gt;&#xA;&gt; Should the mailing list formatting be bungled, it is also available as a gist [here](https://gist.github.com/JeremyRubin/92a9fc4c6531817f66c2934282e71fdf).&#xA;&gt;&#xA;&gt; Non-Destructive TXID Dependencies for Fee Sponsoring&#xA;&gt; ====================================================&#xA;&gt;&#xA;&gt; This BIP proposes a general purpose mechanism for expressing non-destructive (i.e., not requiring&#xA;&gt; the spending of a coin) dependencies on specific transactions being in the same block that can be&#xA;&gt; used to sponsor fees of remote transactions.&#xA;&gt;&#xA;&gt; Motivation&#xA;&gt; ==========&#xA;&gt;&#xA;&gt; The mempool has a variety of protections and guards in place to ensure that miners are economic and&#xA;&gt; to protect the network from denial of service.&#xA;&gt;&#xA;&gt; The rough surface of these policies has some unintended consequences for second layer protocol&#xA;&gt; developers. Applications are either vulnerable to attacks (such as transaction pinning) or must go&#xA;&gt; through great amounts of careful protocol engineering to guard against known mempool attacks.&#xA;&gt;&#xA;&gt; This is insufficient because if new attacks are found, there is limited ability to deploy fixes for&#xA;&gt; them against deployed contract instances (such as open lightning channels). What is required is a&#xA;&gt; fully abstracted primitive that requires no special structure from an underlying transaction in&#xA;&gt; order to increase fees to confirm the transactions.&#xA;&gt;&#xA;&gt; Consensus Specification&#xA;&gt; =======================&#xA;&gt;&#xA;&gt; If a transaction&#39;s last output&#39;s scripPubKey is of the form OP_VER followed by n*32 bytes, where&#xA;&gt; n&gt;1, it is interpreted as a vector of TXIDs (Sponsor Vector). The Sponsor Vector TXIDs  must also be&#xA;&gt; in the block the transaction is validated in, with no restriction on order or on specifying a TXID&#xA;&gt; more than once. This can be accomplished simply with the following patch:&#xA;&gt;&#xA;&gt;&#xA;&gt; ```diff&#xA;&gt; +&#xA;&gt; +    // Extract all required fee dependencies&#xA;&gt; +    std::unordered_set&lt;uint256, SaltedTxidHasher&gt; dependencies;&#xA;&gt; +&#xA;&gt; +    const bool dependencies_enabled = VersionBitsState(pindex-&gt;pprev, chainparams.GetConsensus(), Consensus::DeploymentPos::DEPLOYMENT_TXID_DEPENDENCY, versionbitscache) == ThresholdState::ACTIVE;&#xA;&gt; +    if (dependencies_enabled) {&#xA;&gt; +        for (const auto&amp; tx : block.vtx) {&#xA;&gt; +            // dependency output is if the last output of a txn is OP_VER followed by a sequence of 32*n&#xA;&gt; +            // bytes&#xA;&gt; +            // vout.back() must exist because it is checked in CheckBlock&#xA;&gt; +            const CScript&amp; dependencies_script = tx-&gt;vout.back().scriptPubKey;&#xA;&gt; +            // empty scripts are valid, so be sure we have at least one byte&#xA;&gt; +            if (dependencies_script.size() &amp;&amp; dependencies_script[0] == OP_VER) {&#xA;&gt; +                const size_t size = dependencies_script.size() - 1;&#xA;&gt; +                if (size % 32 == 0 &amp;&amp; size &gt; 0) {&#xA;&gt; +                    for (auto start = dependencies_script.begin() +1, stop = start + 32; start &lt; dependencies_script.end(); start = stop, stop += 32) {&#xA;&gt; +                        uint256 txid;&#xA;&gt; +                        std::copy(start, stop, txid.begin());&#xA;&gt; +                        dependencies.emplace(txid);&#xA;&gt; +                    }&#xA;&gt; +                }&#xA;&gt; +                // No rules applied otherwise, open for future upgrades&#xA;&gt; +            }&#xA;&gt; +        }&#xA;&gt; +        if (dependencies.size() &gt; block.vtx.size()) {&#xA;&gt; +            return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, &#34;bad-dependencies-too-many-target-txid&#34;);&#xA;&gt; +        }&#xA;&gt; +    }&#xA;&gt; +&#xA;&gt;      for (unsigned int i = 0; i &lt; block.vtx.size(); i++)&#xA;&gt;      {&#xA;&gt;          const CTransaction &amp;tx = *(block.vtx[i]);&#xA;&gt; +        if (!dependencies.empty()) {&#xA;&gt; +            dependencies.erase(tx.GetHash());&#xA;&gt; +        }&#xA;&gt;&#xA;&gt;          nInputs += tx.vin.size();&#xA;&gt;&#xA;&gt; @@ -2190,6 +2308,9 @@ bool CChainState::ConnectBlock(const CBlock&amp; block, BlockValidationState&amp; state,&#xA;&gt;          }&#xA;&gt;          UpdateCoins(tx, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), pindex-&gt;nHeight);&#xA;&gt;      }&#xA;&gt; +    if (!dependencies.empty()) {&#xA;&gt; +        return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, &#34;bad-dependency-missing-target-txid&#34;);&#xA;&gt; +    }&#xA;&gt; ```&#xA;&gt;&#xA;&gt; ### Design Motivation&#xA;&gt; The final output of a transaction is an unambiguous location to attach metadata to a transaction&#xA;&gt; such that the data is available for transaction validation. This data could be committed to anywhere,&#xA;&gt; with added implementation complexity, or in the case of Taproot annexes, incompatibility with&#xA;&gt; non-Taproot addresses (although this is not a concern for sponsoring a transaction that does not use&#xA;&gt; Taproot).&#xA;&gt;&#xA;&gt; A bare scriptPubKey prefixed with OP_VER is defined to be invalid in any context, and is trivially&#xA;&gt; provably unspendable and therefore pruneable.&#xA;&gt;&#xA;&gt; If there is another convenient place to put the TXID vector, that&#39;s fine too.&#xA;&gt;&#xA;&gt; As the output type is non-standard, unupgraded nodes will by default not include Transactions&#xA;&gt; containing them in the mempool, limiting risk of an upgrade via this mechanism.&#xA;&gt;&#xA;&gt; Policy Specification&#xA;&gt; ====================&#xA;&gt;&#xA;&gt; The mechanism proposed above is a general specification for inter-transaction dependencies.&#xA;&gt;&#xA;&gt; In this BIP, we only care to ensure a subset of behavior sufficient to replace CPFP and RBF for fee&#xA;&gt; bumping.&#xA;&gt;&#xA;&gt; Thus we restrict the mempool policy such that:&#xA;&gt;&#xA;&gt; 1. No Transaction with a Sponsor Vector may have any child spends; and&#xA;&gt; 1. No Transaction with a Sponsor Vector may have any unconfirmed parents; and&#xA;&gt; 1. The Sponsor Vector must have exactly 1 entry; and&#xA;&gt; 1. The Sponsor Vector&#39;s entry must be present in the mempool; and&#xA;&gt; 1. Every Transaction may have exactly 1 sponsor in the mempool; except&#xA;&gt; 1. Transactions with a Sponsor Vector may not be sponsored.&#xA;&gt;&#xA;&gt;&#xA;&gt; The mempool treats ancestors and descendants limits as follows:&#xA;&gt;&#xA;&gt; 1. Sponsors are counted as children transactions for descendants; but&#xA;&gt; 1. Sponsoring transactions are exempted from any limits saturated at the time of submission.&#xA;&gt;&#xA;&gt; This ensures that within a given package, every child transaction may have a sponsor, but that the&#xA;&gt; mempool prefers to not accept new true children while there are parents that can be cleared.&#xA;&gt;&#xA;&gt; To prevent garbage sponsors, we also require that:&#xA;&gt;&#xA;&gt; 1. The Sponsor&#39;s feerate must be greater than the Sponsored&#39;s ancestor fee rate&#xA;&gt;&#xA;&gt; We allow one Sponsor to replace another subject to normal replacement policies, they are treated as&#xA;&gt; conflicts.&#xA;&gt;&#xA;&gt;&#xA;&gt; ### Design Motivation&#xA;&gt;&#xA;&gt; There are a few other ways to use OP_VER sponsors that are not included. For instance, one could&#xA;&gt; make child chains that are only valid if their parent is in the same block (this is incompatible&#xA;&gt; with CTV, exercise left to reader). These use cases are in a sense incidental to the motivation&#xA;&gt; of this mechanism, and add a lot of implementation complexity.&#xA;&gt;&#xA;&gt; What is wanted is a minimal mechanism that allows arbitrary unconnected third parties to attach&#xA;&gt; fees to an arbitrary transaction. The set of rules given tightly bounds how much extra work the&#xA;&gt; mempool might have to do to account for the new sponsors in the worst case, while providing a &#34;it&#xA;&gt; always works&#34; API for end users that is not subject to traditional issues around pinning.&#xA;&gt;&#xA;&gt; Eventually, rational miners may wish to permit multiple sponsor targets, or multiple sponsoring&#xA;&gt; transactions, but they are not required for the mechanism to work. This is a benefit of the&#xA;&gt; minimality of the consensus rule, it is compatible with future policy should it be implemented.&#xA;&gt;&#xA;&gt;&#xA;&gt; #### Attack Analysis of new Policy&#xA;&gt;&#xA;&gt; In the worst case the new policy can lead to a 1/2 reduction in the number of children allowed&#xA;&gt; (e.g., if there are 13 children submitted, then 12 sponsors, the 25 child limit will saturate&#xA;&gt; before) and a 2x increase in the maximum children (e.g., if there are 25 children submitted, and&#xA;&gt; then each are sponsored). Importantly, even in the latter attack scenario, the DoS surface is not&#xA;&gt; great because the sponsor transactions have no children nor parents.&#xA;&gt;&#xA;&gt; #### Package Relay/Orphan Pool&#xA;&gt;&#xA;&gt; Future policy work might be able to insert sponsors into a special sponsor pool with an eviction&#xA;&gt; policy that would enable sponsors to be queried and tracked for transactions that have too low fee&#xA;&gt; to enter the mempool in the first place. This is treated as a separate concern, as any strides on&#xA;&gt; package relay generally should be able to support sponsors trivially.&#xA;&gt;&#xA;&gt; Reference Implementation&#xA;&gt; ========================&#xA;&gt; A reference implementation demonstrating these rules is available&#xA;&gt; [here](https://github.com/bitcoin/bitcoin/compare/master...JeremyRubin:subsidy-tx). This is a best&#xA;&gt; effort implementation, but has not been carefully audited for correctness and likely diverges from&#xA;&gt; this document in ways that should either be reflected in this document or amended in the code.&#xA;&gt;&#xA;&gt;&#xA;&gt; Best,&#xA;&gt;&#xA;&gt; Jeremy&#xA;&gt;&#xA;&gt;&#xA;&gt;&#xA;&gt; --&#xA;&gt; @JeremyRubin &lt;https://twitter.com/JeremyRubin&gt;&#xA;&gt; &lt;https://twitter.com/JeremyRubin&gt;&#xA;&gt; _______________________________________________&#xA;&gt; bitcoin-dev mailing list&#xA;&gt; bitcoin-dev at lists.linuxfoundation.org&#xA;&gt; https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev&#xA;&gt;&#xA;-------------- next part --------------&#xA;An HTML attachment was scrubbed...&#xA;URL: &lt;http://lists.linuxfoundation.org/pipermail/bitcoin-dev/attachments/20200918/c7e52557/attachment-0001.html&gt;</html></oembed>