Man touching a smart contract concept on a touch screen with his finger.

Emulate any SIGHASH flag without a fork by programming it in a smart contract

This post was first published on Medium.

We develop a novel approach to emulate any SIGHASH flag, by simply coding the logic in a smart contract. It requires no protocol change and is thus much more practical and flexible than adding a hardcoded flag through a fork, every time a new use case is conceived.

SIGHASH Flags

SIGHASH flag decides which part of a transaction is signed by the signature. Specifically, it controls which of the following 10 items are covered by the signature.

SigHash Preimage Format
SigHash Preimage Format

There are three basic flags: SIGHASH_ALL, SIGHASH_NONE,and SIGHASH_SINGLE. There is also a modifier flag SIGHASH_ANYONECANPAY, resulting six combinations.

Summary of different sighash combinations diagram
Summary of different sighash combinations

There have been proposals to add more flags, to customize signing various parts of a transaction not possible under existing flags. One example is listed below:

Proposed Flags

However, each of them has to be hardcoded in the node software and thus requires a potentially contentious fork.

Emulate Any SIGHASH Flag

We provide a framework to emulate arbitrary SIGHASH flag. The new SIGHASH flag can simply be added in the form of a smart contract and thus requires no upgrade to Bitcoin at all. Overall, it works in three steps:

  1. Fetch the current sighash using OP_PUSH_TX
  2. Modify/mask the sighash per the new flag semantics
  3. Check the signature against the new sighash, using ECDSA signature algorithm.

As an example, we implement SIGHASH_ANYPREVOUT.

SIGHASH_ANYPREVOUT

SIGHASH_ANYPREVOUT (previously named SIGHASH_NOINPUT) in BIP-118 excludes the identifier for the UTXO being spent from the signature. A transaction signed with it is not linked to a specific UTXO and can spend any UTXO from addresses with the same public key (or spending conditions).

This can be used, for example, when a user wants to authorize a third-party application to spend her coins. She can pre-sign with SIGHASH_ANYPREVOUT and the application can reuse the signature when spending in her absence, again and again.

The following contract checks that the input signature (i.e., Sig sig) does not cover the UTXO being spent, equivalent to signing using SIGHASH_ANYPREVOUT.

UniversalSighash Contract

Step 1: Line 10 ensures sighash is for the current transaction using OP_PUSH_TX.

Step 2: Line 13–17 set item 2, 3, and 4 of sighash to all 0’s, i.e., blanking out the input UTXO.

Step 3: Line 20 ensures the signature covers exactly the new sighash, using the elliptic curve library. It is equivalent to OP_CHECKSIGFROMSTACK on BTC or OP_DATASIGVERIFY/OP_CHECKDATASIG on BCH.

Extensibility

The same approach can be extended to emulate any flags. For example, blanking item 2 and 3 equals SIGHASH_ANYONECANPAY, and blanking item 6 is essentially SIGHASH_WITHOUT_PREV_VALUE. The expressiveness of Bitcoin smart contracts enables arbitrary flags.

Watch: CoinGeek New York presentation, Smart Contracts & Computation on Bitcoin

New to Bitcoin? Check out CoinGeek’s Bitcoin for Beginners section, the ultimate resource guide to learn more about Bitcoin—as originally envisioned by Satoshi Nakamoto—and blockchain.

[id^="_form"]
[id^="_form"]
[id$="_submit"]
[id$="_submit"]
[^;]
[^;]
[?&]
[?&]
[^&#]
[^&#]
[(d+)]
[(d+)]
[elem.name]
[elem.name]
[+_a-z0-9-'&=]
[+_a-z0-9-'&=]
[+_a-z0-9-']
[+_a-z0-9-']
[a-z0-9-]
[a-z0-9-]
[a-z]
[a-z]
[el.name]
[el.name]
[id^="_form"]
[id^="_form"]
[id$="_submit"]
[id$="_submit"]
[^;]
[^;]
[?&]
[?&]
[^&#]
[^&#]
[(d+)]
[(d+)]
[elem.name]
[elem.name]
[+_a-z0-9-'&=]
[+_a-z0-9-'&=]
[+_a-z0-9-']
[+_a-z0-9-']
[a-z0-9-]
[a-z0-9-]
[a-z]
[a-z]
[el.name]
[el.name]