This is an experimental refactor I wrote to help myself understand script validation logic better. I’m not strongly advocating for it as it touches consensus and I haven’t thoroughly verified it is identical, but I felt it was much clearer than the existing logic, so was worth sharing.
Essentially, the current VerifyScript logic processes all scripts down the same control flow path. This makes the code a bit hard to reason about as the logic for enabling features (e.g., segwit, p2sh, p2sh segwit) is all interleaved cleverly. Furthermore, the use of the stack between execution to communicate conditions for checks (e.g., clearstack) is confusing. In order for me to understand what it was doing and be convinced it is correct, I felt I should re-write it to be less clever in several small steps. This PR is the result of de-clevering this code.
In this PR I:
- duplicate the entire verification logic for the main Script templates we know about.
- Simplify the logic substantially for several types of script.
- Get rid of swapping the stack copy and just running p2sh on a copy of the stack
- Because we know the exact side effects of a SegWit program, we are able to avoid executing the segwit script at all and directly run the segwit program. (We could do the same trick for P2SH, but it is a bigger refactor).
- Moved assertions about flag combinations to be unconditional
- Made a few checks into asserts where we know (based on script type) it will never fail
The code could be further simplified with a bit more duplication (currently the classic script verification code is used in multiple modes), but at current I think it is a nice balance between repetition and clarity.
In the future if new flags are introduced, they should hopefully only be affecting witness programs and not scripts. If this logic needed to be amended, it should be (IMO) easier to patch this version of the function than the current one.
I haven’t benchmarked, but skipping a few extra EvaluateScripts for segwit probably doesn’t hurt.
The Diff for this PR kinda sucks, I recommend just looking at the files side-by-side.