Conditional scripting: how does OP_NOTIF (and OP_IF) operation(s) affect the stack? I'm trying to write a scriptPubKey for a transaction which checks that the hash of the top value in the scriptSig is equal to either one of two fixed values and if so will do the normal transaction signature checks to allow the owner of a specific bitcoin address to spend them; if the scriptSig value is not equal to either one of the fixed values then the spending transaction should be marked as invalid.

I'm trying to keep the scriptPubKey as small as possible, i.e. avoiding hard-coded duplications of pubKeyHash and/or duplications of large chunks of scripting.

Here's what I've got so far...

scriptPubKey:

OP_HASH160 OP_DUP &lt;B&gt; OP_EQUAL OP_DUP
OP_NOTIF OP_DROP OP_DUP &lt;C&gt; OP_EQUAL OP_ENDIF
OP_VERIFY OP_DROP
OP_DUP OP_HASH160 &lt;pubKeyHash&gt; OP_EQUALVERIFY OP_CHECKSIG


The scriptSig would look like this...

scriptSig:

&lt;sig&gt; &lt;pubKey&gt; &lt;A&gt;


The intention is that the transaction would pay out if ( HASH160(A)=B or HASH160(A)=C ) and sig, pubKey and pubKeyHash were all valid in the normal way.

My worry arises from OP_NOTIF; the scripting section of the Bitcoin wiki says that OP_NOTIF removes the top stack value...I assume that it is removed as the OP_NOTIF evaluates it and it is removed regardless of whether it is TRUE or FALSE. Is that correct?

The latter assumption is why I've duplicated the result of the first OP_EQUAL so that I can OP_VERIFY it after the conditional line (assuming that it was TRUE and hasn't otherwise been OP_DROPped by the conditional line).

Would my proposed scriptPubKey have the desired result (without nasty side effects) or is there something smaller/simpler (e.g. using OP_IFDUP instead of an OP_DUP and a conditional OP_DROP) or, if my script is plain wrong, what would a workable script look like?

I should say that the point of this transaction is not to effect a multi-signature transaction; it's to effect a kind of single-signature plus 1-of-2 'passwords' transaction.
So your inputs are:

&lt;sig&gt; &lt;pubkey&gt; &lt;a&gt;


And you want to verify that Hash160(a) == Hash1 or Hash2, and that sig is a valid signature by pubkey? Based on your original script, it looks like you also want to verify that pubkey matches a hash in the script.

So, the best way to do this is like this:

OP_HASH160 OP_DUP &lt;Hash1&gt; OP_EQUAL
// stack now has &lt;sig&gt; &lt;pubkey&gt; &lt;Hash160(a)&gt; &lt;Hash160(a)==Hash1&gt;
OP_SWAP
// stack now has &lt;sig&gt; &lt;pubkey&gt; &lt;Hash160(a)==Hash1&gt; &lt;Hash160(a)&gt;
&lt;Hash2&gt; OP_EQUAL
// stack now has &lt;sig&gt; &lt;pubkey&gt; &lt;Hash160(a)==Hash1&gt; &lt;Hash160(a)==Hash2&gt;
OP_BOOLOR
// stack now has &lt;sig&gt; &lt;pubkey&gt; &lt;Hash160(a)==Hash1 OR Hash160(a)==Hash2&gt;
OP_VERIFY
// stack now contains &lt;sig&gt; &lt;pubkey&gt;, and if &lt;a&gt; didn't pass the test the transaction has already failed
// now just do a norma pay-to-pubkey-hash for the rest of it
OP_DUP OP_HASH160 &lt;Hash160(pubkey)&gt; OP_EQUALVERIFY OP_CHECKSIGVERIFY


(I realize this is an old question, but I didn't see that until I'd already written up the script for it, so I'm posting anyway...)