Skip to content

Add OP_CHECKSIGADD and OP_SUCCESSxxx#644

Merged
apoelstra merged 3 commits intorust-bitcoin:masterfrom
sanket1729:tap_opcodes
Sep 24, 2021
Merged

Add OP_CHECKSIGADD and OP_SUCCESSxxx#644
apoelstra merged 3 commits intorust-bitcoin:masterfrom
sanket1729:tap_opcodes

Conversation

@sanket1729
Copy link
Copy Markdown
Member

Adds support for CHECKSIGADD and OP_SUCCESSxxx. BIP 342 link for reference https://github.com/bitcoin/bips/blob/master/bip-0342.mediawiki#specification .

Also makes a minor change to add INVALIDOPCODE (was previously OP_RETURN)

@Kixunil
Copy link
Copy Markdown
Collaborator

Kixunil commented Sep 7, 2021

If I understand this correctly this change assumes everything is Tapscript. That doesn't seem right as old script will continue to exist. Perhaps put opcodes into different submodules?

@sanket1729
Copy link
Copy Markdown
Member Author

That doesn't seem right as old script will continue to exist. Perhaps put opcodes into different submodules?

Yes, this is correct. I am in favor of doing this, but this seemed too much code diff for opcodes that will never be used (and are not meant to be used). And I was not too concerned about this because this is handled correctly with ScriptContext in rust-miniscript.

If you feel like the diff(a new opcodes submodule along with APIs for it, and updating all usage of current APIs) is worth it, I don't mind updating the PR.

@Kixunil
Copy link
Copy Markdown
Collaborator

Kixunil commented Sep 8, 2021

never be used (and are not meant to be used)

Ah, true, but I think so are OP_SUCCESSxxx until there is a new soft fork making them useful?

@sanket1729
Copy link
Copy Markdown
Member Author

Here is another possible alternative. We keep the opcodes as they are, only add CHECKSIGADD and classify API as shown below

/// Classification context for the opcode. Some opcodes like `OP_RESERVED`
/// abort the script in [`Legacy`] context, but will act as OP_SUCCESS in tapscript
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum ClassifyContext {
    /// Opcode used in tapscript context
    TapScript,
    /// Opcode used in legacy context
    Legacy,
}

impl All {
    /// Classifies an Opcode into a broad class
    #[inline]
    pub fn classify(self, ctx: ClassifyContext) -> Class;

@apoelstra
Copy link
Copy Markdown
Member

I like this alternative ... we already have issues with opcodes having multiple names (e.g. OP_TRUE vs OP_1, or OP_0 vs OP_FALSE vs OP_PUSHBYTES_0, or OP_NOPx vs OP_CSV, etc etc). So I think it's okay to rely on the classifier to figure out what an opcode "really" is.

@sanket1729
Copy link
Copy Markdown
Member Author

Oops, I think I misclicked close

@sanket1729 sanket1729 reopened this Sep 13, 2021
// 3 opcodes
match ctx {
ClassifyContext::TapScript => // 3 opcodes
if self == all::OP_VERIF || self == all::OP_VERNOTIF ||
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nit: I guess that match (self, ctx) would be more readable.

Copy link
Copy Markdown
Collaborator

@dr-orlovsky dr-orlovsky left a comment

Choose a reason for hiding this comment

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

Concept ACK. While I definetly prefer having dedicated script types, suitable for context-specific tasks (like PubkeyScript, SigScript, TapScript etc, as I did in bitcoin_scripts crate), I understand that for the sake of Taproot implementation speed we should go with this for now.

Will be able to review against the spec tomorrow.

@dr-orlovsky dr-orlovsky added the API break This PR requires a version bump for the next release label Sep 13, 2021
@dr-orlovsky dr-orlovsky added this to the 0.28.0 milestone Sep 13, 2021
apoelstra
apoelstra previously approved these changes Sep 14, 2021
Copy link
Copy Markdown
Member

@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

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

ACK b0ad674

Copy link
Copy Markdown
Collaborator

@dr-orlovsky dr-orlovsky left a comment

Choose a reason for hiding this comment

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

Handling of OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY is missed. I will do a separate commit + PR to your branch to refactor classificator match as suggested by @Kixunil to make it more readable and address this issue

Comment on lines +738 to +739
} else if all::OP_PUSHNUM_1.code <= self.code &&
self.code <= all::OP_PUSHNUM_16.code {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nit:

all::PUSHNUM.code..=all::OP_PUSHNUM_16.code.contains(self.code) is more idiomatic; otherwise we will have clippy warning here (when we will start using it)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Will change it. It was a copy-paste of the currently existing code

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

.contains does not work for 1.29 :(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Added to #510 so we don't forget it afterwards.

} else {
Class::Ordinary(Ordinary::try_from_all(self).unwrap())
pub fn classify(self, ctx: ClassifyContext) -> Class {
// 3 opcodes
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nit: we can do use all::* here and get rid of a lot of visual clutter with all:: prefixes

Comment on lines +690 to +695
(self.code >= 126 && self.code <= 129) ||
(self.code >= 131 && self.code <= 134) ||
(self.code >= 137 && self.code <= 138) ||
(self.code >= 141 && self.code <= 142) ||
(self.code >= 149 && self.code <= 153) ||
(self.code >= 187 && self.code <= 254) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nit: 126..=129.contains(self.code) ... is more idiomatic (see my commend below)

(self.code >= 187 && self.code <= 254) {
Class::SuccessOp
// 1 opcode
} else if self == all::OP_RETURN{
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nit: space before {

(self.code >= 187 && self.code <= 254) {
Class::SuccessOp
// 1 opcode
} else if self == all::OP_RETURN{
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Also OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY according to BIP-342 must be classified as ReturnOp here. Potentially we need to rename ReturnOp into Terminating (as they named altogether in spec).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good catch

@sanket1729
Copy link
Copy Markdown
Member Author

I will do a separate commit + PR to your branch to refactor classificator match as suggested by
Kixunil to make it more readable and address this issue

Thanks :)

@dr-orlovsky
Copy link
Copy Markdown
Collaborator

@sanket1729 sorry it happened not to be a PR but just commit - I didn't expect that I can push to your branch directly :( Should I force-push without my commit and to a PR from outside instead?

Copy link
Copy Markdown
Member Author

@sanket1729 sanket1729 left a comment

Choose a reason for hiding this comment

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

ACK c12304012469aaa307bea2ae35e812e21aa697fd (modulo whitespaces). I know Andrew specifically does not like them :P

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

minor nit(don't fix unless needed): This was also an error in my code. 61 opcodes for Legacy and 60 for Tapscript.

Copy link
Copy Markdown
Collaborator

@dr-orlovsky dr-orlovsky Sep 14, 2021

Choose a reason for hiding this comment

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

Fixed since force-push was anyway needed due to end-line space character removal requirement :D

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Thanks :D

@sanket1729
Copy link
Copy Markdown
Member Author

sanket1729 sorry it happened not to be a PR but just commit - I didn't expect that I can push to your branch directly :( Should I force-push without my commit and to a PR from outside instead?

No worries. Looks like I explicitly gave all maintainers the permission to edit it.

dr-orlovsky
dr-orlovsky previously approved these changes Sep 14, 2021
Copy link
Copy Markdown
Collaborator

@dr-orlovsky dr-orlovsky left a comment

Choose a reason for hiding this comment

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

tACK c12304012469aaa307bea2ae35e812e21aa697fd

Copy link
Copy Markdown
Collaborator

@dr-orlovsky dr-orlovsky left a comment

Choose a reason for hiding this comment

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

tACK c75f3ef

Copy link
Copy Markdown
Member Author

@sanket1729 sanket1729 left a comment

Choose a reason for hiding this comment

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

ACK c75f3ef

| (OP_RESERVED1, ctx) | (OP_RESERVED2, ctx)
| (OP_VER, ctx) if ctx == ClassifyContext::Legacy => Class::ReturnOp,

// 71 opcodes operating equally to `OP_RETURN` only in Legacy context
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for doing all this counting, but honestly these numbers were originally there so I could check they all added up to 255 -- and now that we have multiple contexts, they don't, so there isn't so much value here :)

Copy link
Copy Markdown
Member

@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

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

ACK c75f3ef

@apoelstra apoelstra merged commit 9fe840c into rust-bitcoin:master Sep 24, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

API break This PR requires a version bump for the next release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants