Skip to content

Commit

Permalink
fix(202-tariscript): add missing OP_CHECKMULTISIG/VERIFY and update e…
Browse files Browse the repository at this point in the history
…rror codes (#15)

* fix(202-tariscript): add missing OP_CHECKMULTISIG/VERIFY and update error codes

* add changelog
  • Loading branch information
sdbondi authored and CjS77 committed Oct 26, 2022
1 parent 15053c2 commit bf435cf
Showing 1 changed file with 62 additions and 31 deletions.
93 changes: 62 additions & 31 deletions src/RFC-0202_TariScriptOpcodes.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ The same as [`CheckHeightVerify`](#checkheightverifyheight), except that the hei
it to the current block height.

* Fails with `INVALID_INPUT` if there is not a valid integer value on top of the stack.
* Fails with `EMPTY_STACK` if the stack is empty.
* Fails with `STACK_UNDERFLOW` if the stack is empty.
* Fails with `VERIFY_FAILED` if the block height < `height`.


Expand All @@ -154,7 +154,7 @@ Pops the top of the stack as `height`, then pushes the value of (`height` - the
In other words, this opcode replaces the top of the stack with the difference between that value and the current height.

* Fails with `INVALID_INPUT` if there is not a valid integer value on top of the stack.
* Fails with `EMPTY_STACK` if the stack is empty.
* Fails with `STACK_UNDERFLOW` if the stack is empty.

### Stack manipulation

Expand Down Expand Up @@ -201,77 +201,77 @@ Push the associated 32-byte value onto the stack. It will be interpreted as a pu

Drops the top stack item.

* Fails with `EMPTY_STACK` if the stack is empty.
* Fails with `STACK_UNDERFLOW` if the stack is empty.

##### Dup

Duplicates the top stack item.

* Fails with `EMPTY_STACK` if the stack is empty.
* Fails with `STACK_UNDERFLOW` if the stack is empty.
* Fails with `STACK_OVERFLOW` if the stack would exceed the max stack height.

##### RevRot

Reverse rotation. The top stack item moves into 3rd place, e.g. `abc => bca`.

* Fails with `EMPTY_STACK` if the stack has fewer than three items.
* Fails with `STACK_UNDERFLOW` if the stack has fewer than three items.

### Math operations

#### GeZero

Pops the top stack element as `val`. If `val` is greater than or equal to zero, push a 1 to the stack, otherwise push 0.

* Fails with `EMPTY_STACK` if the stack is empty.
* Fails with `STACK_UNDERFLOW` if the stack is empty.
* Fails with `INVALID_INPUT` if `val` is not an integer.

#### GtZero

Pops the top stack element as `val`. If `val` is strictly greater than zero, push a 1 to the stack, otherwise push 0.

* Fails with `EMPTY_STACK` if the stack is empty.
* Fails with `STACK_UNDERFLOW` if the stack is empty.
* Fails with `INVALID_INPUT` if the item is not an integer.

#### LeZero

Pops the top stack element as `val`. If `val` is less than or equal to zero, push a 1 to the stack, otherwise push 0.

* Fails with `EMPTY_STACK` if the stack is empty.
* Fails with `STACK_UNDERFLOW` if the stack is empty.
* Fails with `INVALID_INPUT` if the item is not an integer.

#### LtZero

Pops the top stack element as `val`. If `val` is strictly less than zero, push a 1 to the stack, otherwise push 0.

* Fails with `EMPTY_STACK` if the stack is empty.
* Fails with `STACK_UNDERFLOW` if the stack is empty.
* Fails with `INVALID_INPUT` if the items is not an integer.

##### Add

Pop two items and push their sum

* Fails with `EMPTY_STACK` if the stack has fewer than two items.
* Fails with `STACK_UNDERFLOW` if the stack has fewer than two items.
* Fails with `INVALID_INPUT` if the items cannot be added to each other (e.g. an integer and public key).

##### Sub

Pop two items and push the second minus the top

* Fails with `EMPTY_STACK` if the stack has fewer than two items.
* Fails with `STACK_UNDERFLOW` if the stack has fewer than two items.
* Fails with `INVALID_INPUT` if the items cannot be subtracted from each other (e.g. an integer and public key).

##### Equal

Pops the top two items, and pushes 1 to the stack if the inputs are exactly equal, 0 otherwise. 0 is also pushed if the
values cannot be compared (e.g. integer and pubkey).

* Fails with `EMPTY_STACK` if the stack has fewer than two items.
* Fails with `STACK_UNDERFLOW` if the stack has fewer than two items.

##### EqualVerify

Pops the top two items, and compares their values.

* Fails with `EMPTY_STACK` if the stack has fewer than two items.
* Fails with `STACK_UNDERFLOW` if the stack has fewer than two items.
* Fails with `VERIFY_FAILED` if the top two stack elements are not equal.

### Boolean logic
Expand All @@ -281,42 +281,42 @@ Pops the top two items, and compares their values.
`n` + 1 items are popped from the stack. If the last item popped matches at least one of the first `n` items popped,
push 1 onto the stack. Push 0 otherwise.

* Fails with `EMPTY_STACK` if the stack has fewer than `n` + 1 items.
* Fails with `STACK_UNDERFLOW` if the stack has fewer than `n` + 1 items.

#### OrVerify(n)

`n` + 1 items are popped from the stack. If the last item popped matches at least one of the first `n` items popped,
continue. Fail with `VERIFY_FAILED` otherwise.

* Fails with `EMPTY_STACK` if the stack has fewer than `n` + 1 items.
* Fails with `STACK_UNDERFLOW` if the stack has fewer than `n` + 1 items.

### Cryptographic operations

##### HashBlake256

Pop the top element, hash it with the Blake256 hash function and push the result to the stack.

* Fails with `EMPTY_STACK` if the stack is empty.
* Fails with `STACK_UNDERFLOW` if the stack is empty.

##### HashSha256

Pop the top element, hash it with the SHA256 hash function and push the result to the stack.

* Fails with `EMPTY_STACK` if the stack is empty.
* Fails with `STACK_UNDERFLOW` if the stack is empty.

##### HashSha3

Pop the top element, hash it with the SHA-3 hash function and push the result to the stack.

* Fails with `EMPTY_STACK` if the stack is empty.
* Fails with `STACK_UNDERFLOW` if the stack is empty.

##### CheckSig(Msg)

Pop the public key and then the signature. If the signature signs the 32-byte message, push 1 to the stack, otherwise
push 0.

* Fails with `INVALID_SCRIPT_DATA` if the `Msg` is not a valid 32-byte value.
* Fails with `EMPTY_STACK` if the stack has fewer than 2 items.
* Fails with `STACK_UNDERFLOW` if the stack has fewer than 2 items.
* Fails with `INVALID_INPUT` if the top stack element is not a PublicKey or Commitment
* Fails with `INVALID_INPUT` if the second stack element is not a Signature

Expand All @@ -325,11 +325,28 @@ push 0.
Identical to [`CheckSig`](#checksigmsg), except that nothing is pushed to the stack if the signature is valid, and the
operation fails with `VERIFY_FAILED` if the signature is invalid.

##### CheckMultiSig(Msg)

Pop $m$ signatures from the stack. If $m$ signatures out of the provided $n$ public keys sign the 32-byte message,
push 1 to the stack, otherwise push 0.

* Fails with `INVALID_SCRIPT_DATA` if the `Msg` is not a valid 32-byte value.
* Fails with `INVALID_SCRIPT_DATA` if $m$ or $n$ are zero.
* Fails with `INVALID_SCRIPT_DATA` if $m$ or $n$ are greater than `MAX_MULTISIG_LIMIT (32)`.
* Fails with `INVALID_SCRIPT_DATA` if $m > n$
* Fails with `STACK_UNDERFLOW` if the stack has fewer than $m$ items.
* Fails with `INVALID_INPUT` if $m$ stack elements are not a `Signature`.

##### CheckMultiSigVerify(Msg),

Identical to [`CheckMultiSig`](#checkmultisigmsg), except that nothing is pushed to the stack if the signatures are valid, and the
operation fails with `VERIFY_FAILED` if the signatures are invalid.

##### ToRistrettoPoint,

Pops the top element which must be a valid Ristretto scalar, calculates the corresponding Ristretto point, and pushes this to the stack.

* Fails with `EMPTY_STACK` if the stack is empty.
* Fails with `STACK_UNDERFLOW` if the stack is empty.
* Fails with `INVALID_INPUT` if the top stack element is not a scalar.

### Miscellaneous
Expand All @@ -349,7 +366,7 @@ If `pred` is 0, instructions are popped until `ELSE` or `ENDIF` is encountered.
If `ELSE` is encountered, instructions are executed until `ENDIF` is reached.
`ENDIF` is a marker opcode and a no-op.

* Fails with `EMPTY_STACK` if the stack is empty.
* Fails with `STACK_UNDERFLOW` if the stack is empty.
* If `pred` is anything other than 0 or 1, the script fails with `INVALID_INPUT`.
* If any instruction during execution of the clause causes a failure, the script fails with that failure code.

Expand Down Expand Up @@ -563,20 +580,34 @@ or Bob can spend the output.

### Error codes

| Code | Description |
|:----------------------------|:---------------------------------------------------------------------------------|
| `SCRIPT_TOO_LONG` | The serialised script exceeds 1024 bytes. |
| `SCRIPT_INPUT_TOO_LONG` | The serialised script input exceeds 1024 bytes. |
| `STACK_OVERFLOW` | The stack exceeded 255 elements during script execution |
| `EMPTY_STACK` | There was an attempt to pop an item off an empty stack |
| `INVALID_OPCODE` | The script cannot be deserialised due to an invalid opcode |
| `INVALID_SCRIPT_DATA` | An opcode parameter is invalid or of the wrong type |
| `INVALID_INPUT` | Invalid or incompatible data was popped off the stack as input into an operation |
| `VERIFY_FAILED` | A script condition (typically a `nnnVerify` opcode) failed |
| Code | Description |
|:------------------------|:---------------------------------------------------------------------------------|
| `RETURN` | The serialised script exceeds 1024 bytes. |
| `STACK_OVERFLOW` | The stack exceeded 255 elements during script execution |
| `STACK_UNDERFLOW` | Attempt to pop more items than remain on the stack during script execution |
| `NON_UNIT_LENGTH_STACK` | The stack did not exactly 1 element after script execution |
| `INCOMPATIBLE_TYPES` | An operand was applied to incompatible types |
| `VALUE_EXCEEDS_BOUNDS` | A script opcode resulted in a value that exceeded the maximum or minimum value |
| `INVALID_OPCODE` | The script cannot be deserialised due to an invalid opcode |
| `MISSING_OPCODE` | The script is missing closing opcodes (Else or EndIf) |
| `INVALID_SIGNATURE` | The script contained an invalid signature |
| `INVALID_INPUT` | Invalid or incompatible data was popped off the stack as input into an operation |
| `INVALID_SCRIPT_DATA` | An opcode parameter is invalid or of the wrong type |
| `VERIFY_FAILED` | A script condition (typically a `nnnVerify` opcode) failed |

### Credits

Thanks to [@philipr-za](https://github.com/philipr-za) and [@SWvheerden](https://github.com/SWvheerden) for their input
and contributions to this RFC.


# Change Log

| Date | Change | Author |
|:-------------|:---------------------------------------|:----------|
| 17 Aug 2020 | First draft | CjS77 |
| 8 Mar 2021 | Minor update | philip-za |
| 28 Sep 2022 | Minor update to reflect implementation | sdbondi |


[TariScript]: Glossary.md#tariscript

0 comments on commit bf435cf

Please sign in to comment.