Page MenuHomePhabricator

sighashtype: clarify subtle logic of isDefined()
AbandonedPublic

Authored by markblundeberg on Jan 21 2019, 18:50.

Details

Reviewers
deadalnix
jasonbcox
Group Reviewers
Restricted Project
Summary

I found the logic of isDefined() to be confusing and subtle.
(baseType as a red herring variable name, hidden cast-clipping of forkId)
I think this variable rename and these comments should help future code
readers to see what is the behaviour of this function.

Test Plan

nothing substantial was changed.

Diff Detail

Repository
rABC Bitcoin ABC
Branch
rename-basetype
Lint
Lint Passed
Unit
No Test Coverage
Build Status
Buildable 4619
Build 7301: Bitcoin ABC Buildbot (legacy)
Build 7300: arc lint + arc unit

Event Timeline

jasonbcox requested changes to this revision.Jan 22 2019, 01:01
jasonbcox added a subscriber: jasonbcox.
jasonbcox added inline comments.
src/script/sighashtype.h
70

I think this adds to the confusion because this is not what the code is doing explicitly. Do you think it would benefit from the following in order to make it explicit?
lowBits &= ~0x20;

This revision now requires changes to proceed.Jan 22 2019, 01:01
src/script/sighashtype.h
70

This is a bad idea. You want to clear the flags you know of and check that what remains is in range. At no point you want to touch the undefined flags. One 0-day in that piece of code was enough, there is no need to put efforts into introducing a second one.

src/script/sighashtype.h
70

If we were to simplify this function into one line, it would be: return (sigHash & 0x3f >= SIGHASH_ALL) && (sigHash & 0x3f <= SIGHASH_SINGLE); .
But yeah there is no point in risking making more exploits even with that tiny change. At the very least though I hope the confusing behaviour can be explained.

@jasonbcox it's still red, what am I supposed to do? If you want to refactor you can submit a revision and we can discuss that. The point of this Diff is only to clarify confusing code.

@jasonbcox if you think these comments are a bad idea I can abandon this diff, no worries. I don't want to refactor the code in any way though ... even though it's apparently trivial, this is too scary for me given the history of this particular function. :-D

deadalnix requested changes to this revision.Jan 28 2019, 01:57
deadalnix added inline comments.
src/script/sighashtype.h
70

This comment convey what the code effectively does, which is not what matter - if that was what the user was interested in, the users could do it, it's fairly trivial. The reason a function is used is because the caller do not need or want to care about WHAT this function does. It cares about the contract the function provides, and the contract is: is that sighashtype defined under the current consensus rules.

The approach is to clear known flags and check that what remains is exclusively a valid base hash type. There is a reason why this approach is taken rather than the explicit list of criterion as listed in the comment. It is just not solid. What happen if a criterion is missing ? In one case, we'll get the test using that criteria to start failing, in the other we'll get a 0-day. And this is not just grandstanding as we actually got a 0-day in that code.

74

Going for 0x3f here is the same issue.

This revision now requires changes to proceed.Jan 28 2019, 01:57
markblundeberg added inline comments.
src/script/sighashtype.h
74

Yes, the reason I find this confusing is that the original code uses baseType = BaseSigHashType(...), so you would expect that baseType should be identical to getBaseType() which ranges 0--0x1f.

But that is not at all the case. For invalid sighashes with bit 0x20 set, baseType is distinct from getBaseType(). Therefore it shouldn't be called 'baseType' at all.

The conversion BaseSigHashType() is also misleading since it actually is an implicit reduction from uint32 (with forkid) to uint8 (without forkid). I.e., it doesn't create a basetype at all but instead its function is to strip forkid.

Maybe there is a better way to clarify this. I will abandon this and someone else can figure it out.