diff --git a/sips/sip-020/sip-020-bitwise-ops.md b/sips/sip-020/sip-020-bitwise-ops.md new file mode 100644 index 00000000..f744e4e3 --- /dev/null +++ b/sips/sip-020/sip-020-bitwise-ops.md @@ -0,0 +1,305 @@ +# Preamble + +SIP Number: 020 + +Title: Bitwise Operations in Clarity + +Authors: Cyle Witruk , Brice Dobry + + +Consideration: Technical, Governance + +Type: Consensus + +Status: Activation-in-Progress + +Created: 12 November 2022 + +License: CC0-1.0 + +Sign-off: Jason Schrader , Jesse Wiley + +Layer: Consensus (hard fork) + +Discussions-To: https://github.com/stacksgov/sips + +# Abstract + +This SIP adds bitwise operations to the Clarity language which could simplify +the implementation of smart contracts that require manipulation of bits. The +changes include the addition of the following operations: + +- Bitwise Xor (`bit-xor`) +- Bitwise And (`bit-and`) +- Bitwise Or (`bit-or`) +- Bitwise Not (`bit-not`) +- Binary Left Shift (`bit-shift-left`) +- Binary Right Shift (`bit-shift-right`) + +# License and Copyright + +This SIP is made available under the terms of the Creative Commons CC0 1.0 +Universal license, available at +https://creativecommons.org/publicdomain/zero/1.0/ This SIP's copyright is held +by the Stacks Open Internet Foundation. + +# Introduction + +Bitwise operations are common in other programming languages. Common algorithms, +including many used in encryption, or the ability to set and check flags in a +bit field for example, would be much more difficult to implement without the use +of these operations. When executing a contract using these operations, the +common hardware on which miners and nodes are likely to be running can all +perform these operations very efficiently -- these are typically single cycle +operations. Note that the addition of these bitwise operations commits the +Clarity VM to using 2's complement to represent integers. + +# Specification + +## Bitwise Xor (`bit-xor`) + +`(bit-xor i1 i2...)` + +- **Inputs:** int, ... | uint, ... +- **Output:** int | uint + +Returns the result of bitwise exclusive or'ing a variable number of integer +inputs. + +| Bit in i1 | Bit in i2 | Bit in Output | +| --------- | --------- | ------------- | +| 0 | 0 | 0 | +| 0 | 1 | 1 | +| 1 | 0 | 1 | +| 1 | 1 | 0 | + +The following example uses only 8 bits to make it easier to follow. Actual +Clarity values are 128 bits. + +``` +(bit-xor 17 30) ;; Return 15 +;; Binary representation: +;; i1 (17): 00010001 +;; i2 (30): 00011110 +;; Output (15): 00001111 +``` + +### Examples + +``` +(bit-xor 1 2) ;; Returns 3 +(bit-xor 120 280) ;; Returns 352 +(bit-xor -128 64) ;; Returns -64 +(bit-xor u24 u4) ;; Returns u28 +(bit-xor 1 2 4 -1) ;; Returns -8 +``` + +## Bitwise And (`bit-and`) + +`(bit-and i1 i2...)` + +- **Inputs:** int, ... | uint, ... +- **Output:** int | uint + +Returns the result of bitwise and'ing a variable number of integer inputs. + +| Bit in i1 | Bit in i2 | Bit in Output | +| --------- | --------- | ------------- | +| 0 | 0 | 0 | +| 0 | 1 | 0 | +| 1 | 0 | 0 | +| 1 | 1 | 1 | + +The following example uses only 8 bits to make it easier to follow. Actual +Clarity values are 128 bits. + +``` +(bit-and 17 30) ;; Return 16 +;; Binary representation: +;; i1 (17): 00010001 +;; i2 (30): 00011110 +;; Output (16): 00010000 +``` + +### Examples + +``` +(bit-and 24 16) ;; Returns 16 +(bit-and 28 24 -1) ;; Returns 24 +(bit-and u24 u16) ;; Returns u16 +(bit-and -128 -64) ;; Returns -128 +(bit-and 28 24 -1) ;; Returns 24 +``` + +## Bitwise Or (`bit-or`) + +`(bit-or i1 i2...)` + +- **Inputs:** int, ... | uint, ... +- **Outputs:** int | uint + +Returns the result of bitwise inclusive or'ing a variable number of integer +inputs. + +| Bit in i1 | Bit in i2 | Bit in Output | +| --------- | --------- | ------------- | +| 0 | 0 | 0 | +| 0 | 1 | 1 | +| 1 | 0 | 1 | +| 1 | 1 | 1 | + +The following example uses only 8 bits to make it easier to follow. Actual +Clarity values are 128 bits. + +``` +(bit-or 17 30) ;; Return 31 +;; Binary representation: +;; i1 (17): 00010001 +;; i2 (30): 00011110 +;; Output (31): 00011111 +``` + +### Examples + +``` +(bit-or 4 8) ;; Returns 12 +(bit-or 1 2 4) ;; Returns 7 +(bit-or 64 -32 -16) ;; Returns -16 +(bit-or u2 u4 u32) ;; Returns u38 +``` + +## Bitwise Not (`bit-not`) + +`(bit-not i1)` + +- **Inputs:** int | uint +- **Output:** int | uint + +Returns the one's compliment (sometimes also called the bitwise compliment or +not operator) of `i1`, effectively reversing the bits in `i1`. + +In other words, every bit that is `1` in `ì1` will be `0` in the result. +Conversely, every bit that is `0` in `i1` will be `1` in the result. + +| Bit in i1 | Bit in Output | +| --------- | ------------- | +| 0 | 1 | +| 1 | 0 | + +The following example uses only 8 bits to make it easier to follow. Actual +Clarity values are 128 bits. + +``` +(bit-not u41) ;; Return u214 +;; Binary representation: +;; i1 (41): 00101001 +;; Output (214): 11010110 +``` + +### Examples + +``` +(bit-not 3) ;; Returns -4 +(bit-not u128) ;; Returns u340282366920938463463374607431768211327 +(bit-not 128) ;; Returns -129 +(bit-not -128) ;; Returns 127 +``` + +## Bitwise Left Shift (`bit-shift-left`) + +`(bit-shift-left i1 shamt)` + +- **Inputs:** int, uint | uint, uint +- **Outputs:** int | uint + +Shifts all bits in `i1` to the left by the number of places specified in `shamt` +modulo 128 (the bit width of Clarity integers). New bits are filled with zeros. + +Note that there is a deliberate choice made to ignore arithmetic overflow for +this operation. In use cases where overflow should be detected, developers +should use `*`, `/`, and `pow` instead of the shift operators. + +The following example uses only 8 bits to make it easier to follow. Actual +Clarity values are 128 bits. + +``` +(bit-shift-left 6 u3) ;; Return 48 +;; Binary representation: +;; Input (6): 00000110 +;; Output (48): 00110000 +``` + +### Examples + +``` +(bit-shift-left 16 u2) ;; Returns 64 +(bit-shift-left -64 u1) ;; Returns -128 +(bit-shift-left u4 u2) ;; Returns u16 +(bit-shift-left 123 u9999999999) ;; Returns -170141183460469231731687303715884105728 (== 123 bit-shift-left 127) +(bit-shift-left u123 u9999999999) ;; Returns u170141183460469231731687303715884105728 (== u123 bit-shift-left 127) +(bit-shift-left -1 u7) ;; Returns -128 +(bit-shift-left -1 u128) ;; Returns -1 +``` + +## Bitwise Right Shift (`bit-shift-right`) + +`(bit-shift-right i1 shamt)` + +- **Inputs:** int, uint | uint, uint +- **Output:** int | uint + +Shifts all the bits in `i1` to the right by the number of places specified in +`shamt` modulo 128 (the bit width of Clarity integers). When `i1` is a `uint` +(unsigned), new bits are filled with zeros. When `i1` is an `int` (signed), the +sign is preserved, meaning that new bits are filled with the value of the +previous sign-bit. + +Note that there is a deliberate choice made to ignore arithmetic overflow for +this operation. In use cases where overflow should be detected, developers +should use `*`, `/`, and `pow` instead of the shift operators. + +The following example uses only 8 bits to make it easier to follow. Actual +Clarity values are 128 bits. + +``` +(bit-shift-right u170 u1) ;; Return u85 +;; Binary representation: +;; Input (u170): 10101010 +;; Output (u85): 01010101 +``` + +### Examples + +``` +(bit-shift-right 2 u1) ;; Returns 1 +(bit-shift-right 128 u2) ;; Returns 32 +(bit-shift-right -64 u1) ;; Returns -32 +(bit-shift-right u128 u2) ;; Returns u32 +(bit-shift-right 123 u9999999999) ;; Returns 0 +(bit-shift-right u123 u9999999999) ;; Returns u0 +(bit-shift-right -128 u7) ;; Returns -1 +(bit-shift-right -256 u1) ;; Returns -128 +(bit-shift-right 5 u2) ;; Returns 1 +(bit-shift-right -5 u2) ;; Returns -2 +``` + +# Related work + +Not applicable + +# Backwards Compatibility + +Because this SIP introduces new Clarity operators, it is a consensus-breaking +change. A contract that uses one of these new operators would be invalid before +this SIP is activated, and valid after it is activated. + +# Activation + +This SIP will be a rider on SIP-015. It will be considered activated if and only +if SIP-015 (and Stacks 2.1) is activated. + +# Reference Implementations + +- https://github.com/stacks-network/stacks-blockchain/pull/3389 +- See also discussions in + https://github.com/stacks-network/stacks-blockchain/pull/3382