Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add policy: null signature for failed CHECK(MULTI)SIG #8634

Merged
merged 1 commit into from Sep 27, 2016

Conversation

jl2012
Copy link
Contributor

@jl2012 jl2012 commented Aug 31, 2016

Intended for 0.13.1

This PR adds a new policy to require that signature(s) must be empty vector for failed CHECK(MULTI)SIG operations.

This fixes malleability for some forms of scripts, for example:

"key 1" CHECKSIG IF "key 2" CHECKSIG ELSE "key 3" CHECKSIGVERIFY "locktime" CLTV ENDIF

which is spendable with both sig 1 and sig 2 anytime, or sig 3 only after locktime

Without this new policy, a relay node may inject arbitrary BIP66-compliant data to the scriptSig/witness when the ELSE branch is executed.

This may become a softfork in the future. I will prepare for a BIP later

@jl2012
Copy link
Contributor Author

jl2012 commented Sep 2, 2016

Please tag 0.13.1

@fanquake fanquake added this to the 0.13.1 milestone Sep 2, 2016
@btcdrak
Copy link
Contributor

btcdrak commented Sep 2, 2016

Concept ACK

@jl2012
Copy link
Contributor Author

jl2012 commented Sep 6, 2016

This is an implementation of NULLFAIL of BIP146, except the activation logic:

https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki#NULLFAIL

["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "OK", "BIP66 and NULLFAIL-compliant"],
["1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "OK", "BIP66 and NULLFAIL-compliant, not NULLDUMMY-compliant"],
["1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL,NULLDUMMY", "SIG_NULLDUMMY", "BIP66 and NULLFAIL-compliant, not NULLDUMMY-compliant"],
["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0x09 0x300602010102010101", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66 and NULLFAIL-compliant"],
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments for the following few lines should be read as "BIP66-compliant but not NULLFAIL-compliant". Will fix

@NicolasDorier
Copy link
Contributor

NicolasDorier commented Sep 6, 2016

CodeReview ACK bb50e7683d97ea6cc69fa5837a51fba54643f2cc

@dcousens
Copy link
Contributor

concept ACK

@btcdrak
Copy link
Contributor

btcdrak commented Sep 12, 2016

ACK d071bfd

@rubensayshi
Copy link
Contributor

utACK

@gmaxwell
Copy link
Contributor

concept ACK, utACK, will review more.

Copy link
Contributor

@afk11 afk11 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tACK & code review bb50e76

@CodeShark
Copy link
Contributor

utACK bb50e7683d97ea6cc69fa5837a51fba54643f2cc

@@ -902,6 +906,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);

int nKeysCount = CScriptNum(stacktop(-i), fRequireMinimal).getint();
int ikey2 = nKeysCount + 2;
Copy link
Contributor

@CodeShark CodeShark Sep 22, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small nit: moving this line below the next will avoid performing the addition if the range check on nKeysCount fails. Also, since this is only used for cleanup, I would suggest giving the variable a more descriptive name like nNonSigCleanupItems or adding a comment describing what it's for.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed with 5d23cfe

@jl2012 jl2012 force-pushed the nullfail branch 2 times, most recently from be29b35 to 1912bf1 Compare September 22, 2016 07:59
@jtimon
Copy link
Contributor

jtimon commented Sep 22, 2016

ut ACK 1912bf1

Copy link
Member

@instagibbs instagibbs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK 1912bf12d06011f989c0db4ae7cbf433cfff18da

I'd like to see the commits squashed though.

@@ -880,6 +880,10 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
bool fSuccess = checker.CheckSig(vchSig, vchPubKey, scriptCode, sigversion);

popstack(stack);

if (!fSuccess && (flags & SCRIPT_VERIFY_NULLFAIL) && stacktop(-1).size())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit of nits: just check vchSig.size() instead, move before popstack

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed with cd102b5

@@ -908,6 +912,9 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
if (nOpCount > MAX_OPS_PER_SCRIPT)
return set_error(serror, SCRIPT_ERR_OP_COUNT);
int ikey = ++i;
// ikey2 is the position of last non-signature item in the stack. Top stack item = 1.
// With SCRIPT_VERIFY_NULLFAIL, this is used for cleanup if operation fails.
int ikey2 = nKeysCount + 2;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code section is a bit confusing already with all these different counters, why not set

int ikey2 = i;

right after the following line:

i += nKeysCount;

below? From there the two values diverge.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer the current way as it's clearly correct. The way that i is calculated looks a bit obscure to me

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I misread. Yes, the i is calculated quite oddly, but it's the value we're calculating yet again here.

@CodeShark
Copy link
Contributor

utACK cd102b57a4c148fb93428e656e7282732c65033c

Copy link
Member

@sipa sipa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK

@btcdrak
Copy link
Contributor

btcdrak commented Sep 27, 2016

needs rebase

@jl2012
Copy link
Contributor Author

jl2012 commented Sep 27, 2016

rebased

@laanwj laanwj merged commit e41bd44 into bitcoin:master Sep 27, 2016
laanwj added a commit that referenced this pull request Sep 27, 2016
e41bd44 Add policy: null signature for failed CHECK(MULTI)SIG (Johnson Lau)
laanwj pushed a commit to laanwj/bitcoin that referenced this pull request Oct 13, 2016
codablock pushed a commit to codablock/dash that referenced this pull request Jan 12, 2018
…)SIG

e41bd44 Add policy: null signature for failed CHECK(MULTI)SIG (Johnson Lau)
andvgal pushed a commit to energicryptocurrency/gen2-energi that referenced this pull request Jan 6, 2019
…)SIG

e41bd44 Add policy: null signature for failed CHECK(MULTI)SIG (Johnson Lau)
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet