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

[BIP-117] Tail call semantics #12132

Closed
wants to merge 3 commits into from
Closed

[BIP-117] Tail call semantics #12132

wants to merge 3 commits into from

Conversation

kallewoof
Copy link
Member

Implements BIP 117 as policy rules for transaction relay, causing transactions which violate the new tail-call semantics to be treated as non-standard. This is not the soft-fork activation logic needed to use tail-call scripts in production.

Tail-call semantics is a sort of user-programmable P2SH which combines well with BIP 116's MERKLEBRANCHVERIFY to allows for a script to commit to a practically unbounded number of code pathways, and then reveal the actual code pathway used at spend time, achieving a form of generalized MAST.

script = CScript(policyScript.begin(), policyScript.end());
popstack(stack);
// Only allow one tail-call:
allow_tail_call = false;
Copy link

Choose a reason for hiding this comment

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

Apologies for being annoying//this may be a stupid question: but why only do TCO once?

Copy link
Contributor

Choose a reason for hiding this comment

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

Choose a reason for hiding this comment

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

Thank you very much!

@@ -1039,6 +1043,20 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
if (!vfExec.empty())
return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL);

if (allow_tail_call && !stack.empty() && ((stack.size() + altstack.size()) >= 2) && CastToBool(stack.back())) {
Copy link

Choose a reason for hiding this comment

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

The third condition of the specification is not checked:

https://github.com/bitcoin/bips/blob/master/bip-0117.mediawiki#specification

the following Nth element on the main stack (or alt stack, as above) is between 1 and 520 bytes,

Should it?

About being able to concatenate up to 17 elements to form the script: why stop at 17? Would be great to include some rationale about this in the BIP, or possibly extend the BIP to allow longer scripts if that makes sense.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oops. The current version of this pull request does not match the BIP. My fault -- we were so busy converting MERKLEBRANCHVERIFY to be multi-element that it slipped though cracks. The BIP was updated to the new scheme which allows the script to be split across multiple stack elements, but this PR does not reflect that. I will update this PR to match the BIP.

To answer your question though, the reason that a maximum number of 17 elements is allowed, is due to the fact that only OP_1 through OP_16 are provided as single-byte opcodes, and 17*520 = 8,840 bytes is close enough to the maximum script limit of 10,000 bytes that it doesn't necessarily make sense to have a further exception for 18 or 19 pushes to reach the full limit. Particularly since MAST eliminates the need for such long scripts in the first place.

Copy link

Choose a reason for hiding this comment

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

Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

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

The PR has been updated to allow for multiple script elements, as specified in BIP 117.

@maaku
Copy link
Contributor

maaku commented Jan 12, 2018

Travis build error looks like a transient issue.

If, at the end of script execution, the stack has more than one item on it, the top-most element is interpreted as a serialized script and executed, with the remaining elements on the stack as inputs. No state is maintained, and termination of the subscript terminates execution of the script as a whole. Only one tail-call is allowed per script execution, and neither P2SH nor segwit nor execution of the scriptSig results in tail-call semantics, although the P2SH or segwit redeem script can make a single tail-call.
…sactions that fail tail-call verification will be rejected from the mempool, making it easier to test and later soft-fork activate this feature. Blocks which contain transactions with "invalid" tail-call semantics will still be accepted; this is *not* the soft-fork required to use tail-call semantics in production.
@kallewoof
Copy link
Member Author

I'm closing this for now. If a better suited champion appears I'll help out where I can. Ping @btcdrak @maaku.

@kallewoof kallewoof closed this Sep 19, 2018
@kallewoof kallewoof deleted the tcs branch January 4, 2020 02:17
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Feb 15, 2022
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

6 participants