Page MenuHomePhabricator

add rule for **minimal** push only in scriptSig
Closed, SpitePublic

Description

Reference: https://github.com/bitcoincashorg/bitcoincash.org/pull/359/files

Currently, all transactions can be modified by miners before inclusion in blocks, something known as 'third-party malleability'. Modifying transactions changes their transaction ID and invalidates all descendant transactions, and it is silly that we allow this to occur for any transaction when it's easily prevented for 99% of transactions.

BCH has made a serious effort to stop this so far, with the adoption of consensus rules:

  • The original P2SH required that the scriptSig only contains push opertations.
  • LOW_S, DERSIG, and STRICTENC require that ECDSA signatures and hashtype must be a specific canonical form.
  • The PUSHONLY rule requires not just P2SH but ALL transactions to use only pushes in scriptSig.
  • CLEANSTACK rule stops the inclusion of extra pushes.

However, all these efforts are thus far completely ineffective since there still remains a trivial and well known malleability mechanism that affects all transactions with nonempty scriptSigs (i.e., 100% of normal economic transactions): there are multiple ways to push the same data in the scriptSig, by mutating PUSHN <-> PUSHDATA1 <-> PUSHDATA2 <-> PUSHDATA4 <-> OP_n.

Currently, push forms are only restricted by a non-consensus rule (MINIMALDATA). Unfortunately MINIMALDATA is unnecessarily over-broad and over-complex, and doesn't make sense as a consensus rule. Not only does it affect scriptSig, but also unnecessarily restricts push forms inside of scriptPubKeys and redeemscripts (which are not a malleability concern). Also for some reason, MINIMALDATA also includes restrictions on the way that numbers are encoded (which is completely unrelated to what opcodes are used to push bytes on stack).

The proposed rule is the simplest necessary, entirely analogous to SIG_PUSHONLY but it actually is effective in reducing malleability: to enforce that for any given stack created by scriptSig execution, the scriptSig must have been encoded in a canonical, minimal push-only form. It imposes no unnecessary restrictions on pushes in scriptPubKey and redeemScript, and unlike MINIMALDATA does not conflate number encoding with push opcodes.

Unlike MINIMALDATA, rules on scriptSig execution (like SIG_PUSHONLY, and the proposed rule) cannot make any scripts unspendable, hence they are 'perfectly safe' to adopt. Once adopted, the minimal scriptsig rule would subsume the SIG_PUSHONLY rule which could then be removed retroactively.