├── .nojekyll ├── LICENSE ├── README.md ├── combinations.js ├── index.html └── old-index.html /.nojekyll: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS 10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM 11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED 12 | HEREUNDER. 13 | 14 | Statement of Purpose 15 | 16 | The laws of most jurisdictions throughout the world automatically confer 17 | exclusive Copyright and Related Rights (defined below) upon the creator 18 | and subsequent owner(s) (each and all, an "owner") of an original work of 19 | authorship and/or a database (each, a "Work"). 20 | 21 | Certain owners wish to permanently relinquish those rights to a Work for 22 | the purpose of contributing to a commons of creative, cultural and 23 | scientific works ("Commons") that the public can reliably and without fear 24 | of later claims of infringement build upon, modify, incorporate in other 25 | works, reuse and redistribute as freely as possible in any form whatsoever 26 | and for any purposes, including without limitation commercial purposes. 27 | These owners may contribute to the Commons to promote the ideal of a free 28 | culture and the further production of creative, cultural and scientific 29 | works, or to gain reputation or greater distribution for their Work in 30 | part through the use and efforts of others. 31 | 32 | For these and/or other purposes and motivations, and without any 33 | expectation of additional consideration or compensation, the person 34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she 35 | is an owner of Copyright and Related Rights in the Work, voluntarily 36 | elects to apply CC0 to the Work and publicly distribute the Work under its 37 | terms, with knowledge of his or her Copyright and Related Rights in the 38 | Work and the meaning and intended legal effect of CC0 on those rights. 39 | 40 | 1. Copyright and Related Rights. A Work made available under CC0 may be 41 | protected by copyright and related or neighboring rights ("Copyright and 42 | Related Rights"). Copyright and Related Rights include, but are not 43 | limited to, the following: 44 | 45 | i. the right to reproduce, adapt, distribute, perform, display, 46 | communicate, and translate a Work; 47 | ii. moral rights retained by the original author(s) and/or performer(s); 48 | iii. publicity and privacy rights pertaining to a person's image or 49 | likeness depicted in a Work; 50 | iv. rights protecting against unfair competition in regards to a Work, 51 | subject to the limitations in paragraph 4(a), below; 52 | v. rights protecting the extraction, dissemination, use and reuse of data 53 | in a Work; 54 | vi. database rights (such as those arising under Directive 96/9/EC of the 55 | European Parliament and of the Council of 11 March 1996 on the legal 56 | protection of databases, and under any national implementation 57 | thereof, including any amended or successor version of such 58 | directive); and 59 | vii. other similar, equivalent or corresponding rights throughout the 60 | world based on applicable law or treaty, and any national 61 | implementations thereof. 62 | 63 | 2. Waiver. To the greatest extent permitted by, but not in contravention 64 | of, applicable law, Affirmer hereby overtly, fully, permanently, 65 | irrevocably and unconditionally waives, abandons, and surrenders all of 66 | Affirmer's Copyright and Related Rights and associated claims and causes 67 | of action, whether now known or unknown (including existing as well as 68 | future claims and causes of action), in the Work (i) in all territories 69 | worldwide, (ii) for the maximum duration provided by applicable law or 70 | treaty (including future time extensions), (iii) in any current or future 71 | medium and for any number of copies, and (iv) for any purpose whatsoever, 72 | including without limitation commercial, advertising or promotional 73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each 74 | member of the public at large and to the detriment of Affirmer's heirs and 75 | successors, fully intending that such Waiver shall not be subject to 76 | revocation, rescission, cancellation, termination, or any other legal or 77 | equitable action to disrupt the quiet enjoyment of the Work by the public 78 | as contemplated by Affirmer's express Statement of Purpose. 79 | 80 | 3. Public License Fallback. Should any part of the Waiver for any reason 81 | be judged legally invalid or ineffective under applicable law, then the 82 | Waiver shall be preserved to the maximum extent permitted taking into 83 | account Affirmer's express Statement of Purpose. In addition, to the 84 | extent the Waiver is so judged Affirmer hereby grants to each affected 85 | person a royalty-free, non transferable, non sublicensable, non exclusive, 86 | irrevocable and unconditional license to exercise Affirmer's Copyright and 87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 88 | maximum duration provided by applicable law or treaty (including future 89 | time extensions), (iii) in any current or future medium and for any number 90 | of copies, and (iv) for any purpose whatsoever, including without 91 | limitation commercial, advertising or promotional purposes (the 92 | "License"). The License shall be deemed effective as of the date CC0 was 93 | applied by Affirmer to the Work. Should any part of the License for any 94 | reason be judged legally invalid or ineffective under applicable law, such 95 | partial invalidity or ineffectiveness shall not invalidate the remainder 96 | of the License, and in such case Affirmer hereby affirms that he or she 97 | will not (i) exercise any of his or her remaining Copyright and Related 98 | Rights in the Work or (ii) assert any associated claims and causes of 99 | action with respect to the Work, in either case contrary to Affirmer's 100 | express Statement of Purpose. 101 | 102 | 4. Limitations and Disclaimers. 103 | 104 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 105 | surrendered, licensed or otherwise affected by this document. 106 | b. Affirmer offers the Work as-is and makes no representations or 107 | warranties of any kind concerning the Work, express, implied, 108 | statutory or otherwise, including without limitation warranties of 109 | title, merchantability, fitness for a particular purpose, non 110 | infringement, or the absence of latent or other defects, accuracy, or 111 | the present or absence of errors, whether or not discoverable, all to 112 | the greatest extent permissible under applicable law. 113 | c. Affirmer disclaims responsibility for clearing rights of other persons 114 | that may apply to the Work or any use thereof, including without 115 | limitation any person's Copyright and Related Rights in the Work. 116 | Further, Affirmer disclaims responsibility for obtaining any necessary 117 | consents, permissions or other rights required for any use of the 118 | Work. 119 | d. Affirmer understands and acknowledges that Creative Commons is not a 120 | party to this document and has no duty or obligation with respect to 121 | this CC0 or use of the Work. 122 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bitvm workshop 2 | Basic bitvm app that demonstrates 5 principles of bitvm: 3 | - Multiparty computation 4 | - State transfer 5 | - Off chain computation 6 | - Fraud proofs 7 | - Tapleaf guards 8 | 9 | # Warning 10 | The code is a work in progress and doesn't fully work yet, do not expect much 11 | 12 | # Workshop video 13 | https://www.youtube.com/watch?v=LwH9fhY4uGA 14 | 15 | # Slideshow 16 | http://tinyurl.com/bitvm-workshop 17 | 18 | # How to use 19 | - Open up [Mutiny Textnet Tx Broadcaster](https://mutinynet.com/tx/push) 20 | - And [Mutiny Testnet Faucet](https://faucet.mutinynet.com/) 21 | - [Open bit tac toe by clicking this link](https://supertestnet.github.io/bitvm-workshop/) 22 | - On the bit tac toe page, open your web browser's console (ctrl+shift+i in firefox, otherwise Menu > More Tools > Web Developer Tools > Console) 23 | - Click Play and follow the promps. They are a bit confusing so consider watching [this video](https://www.youtube.com/watch?v=LwH9fhY4uGA) to see how it's *supposed* to work. And remember, this software is only half baked, so be prepared for disappointment 24 | 25 | # Resources 26 | - whitepaper: https://bitvm.org/bitvm.pdf 27 | - WIP implementation: https://github.com/supertestnet/tapleaf-circuits/ 28 | - bitcoin magazine explainer: https://bitcoinmagazine.com/technical/the-big-deal-with-bitvm-arbitrary-computation-now-possible-on-bitcoin-without-a-fork 29 | - simple explainer: https://github.com/fiksn/bitvm-explained 30 | - LN+ explainer: https://lightningnetwork.plus/posts/450 31 | - base58 explainer: https://twitter.com/base58btc/status/1711728898730242112 32 | -------------------------------------------------------------------------------- /combinations.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT license. 3 | * http://www.opensource.org/licenses/mit-license.php 4 | * 5 | * References: 6 | * http://www.ruby-doc.org/core-2.0/Array.html#method-i-combination 7 | * http://www.ruby-doc.org/core-2.0/Array.html#method-i-permutation 8 | */ 9 | 10 | (function(root, factory) { 11 | if (typeof define === 'function' && define.amd) { 12 | define([], factory) 13 | } else if (typeof exports === 'object') { 14 | module.exports = factory() 15 | } else { 16 | root.G = factory() 17 | } 18 | }(this, function() { 19 | 20 | 'use strict' 21 | 22 | /** @exports G */ 23 | const G = { 24 | 25 | clones: false, 26 | 27 | /** 28 | * Calculates a factorial 29 | * @param {Number} n - The number to operate the factorial on. 30 | * @returns {Number} n! 31 | */ 32 | factorial: function factorial(n) { 33 | for (var ans = 1; n; ans *= n--); 34 | return ans 35 | }, 36 | 37 | /** 38 | * Converts a number to the factorial number system. Digits are in least significant order. 39 | * @param {Number} n - Integer in base 10 40 | * @returns {Array} digits of n in factoradic in least significant order 41 | */ 42 | factoradic: function factoradic(n) { 43 | let radix = 1 44 | for (var digit = 1; radix < n; radix *= ++digit); 45 | if (radix > n) radix /= digit-- 46 | let result = [0] 47 | for (; digit; radix /= digit--) { 48 | result[digit] = Math.floor(n / radix) 49 | n %= radix 50 | } 51 | return result 52 | }, 53 | 54 | /** 55 | * Calculates the number of possible permutations of "k" elements in a set of size "n". 56 | * @param {Number} n - Number of elements in the set. 57 | * @param {Number} k - Number of elements to choose from the set. 58 | * @returns {Number} n P k 59 | */ 60 | P: function P(n, k) { 61 | return this.factorial(n) / this.factorial(n - k) 62 | }, 63 | 64 | /** 65 | * Calculates the number of possible combinations of "k" elements in a set of size "n". 66 | * @param {Number} n - Number of elements in the set. 67 | * @param {Number} k - Number of elements to choose from the set. 68 | * @returns {Number} n C k 69 | */ 70 | C: function C(n, k) { 71 | return this.P(n, k) / this.factorial(k) 72 | }, 73 | 74 | /** 75 | * Higher level method for counting number of possible combinations of "k" elements from a set of size "n". 76 | * @param {Number} n - Number of elements in the set. 77 | * @param {Number} k - Number of elements to choose from the set. 78 | * @param {Object} [options] 79 | * @param {Boolean} options.replace - Is replacement allowed after each choice? 80 | * @param {Boolean} options.ordered - Does the order of the choices matter? 81 | * @returns {Number} Number of possible combinations. 82 | */ 83 | choices: function choices(n, k, options = {}) { 84 | if (options.replace) { 85 | if (options.ordered) { 86 | return Math.pow(n, k) 87 | } else { 88 | return this.C(n + k - 1, k) 89 | } 90 | } else { 91 | if (options.ordered) { 92 | return this.P(n, k) 93 | } else { 94 | return this.C(n, k) 95 | } 96 | } 97 | }, 98 | 99 | /** 100 | * Generates all combinations of a set. 101 | * @param {Array|String} arr - The set of elements. 102 | * @param {Number} [size=arr.length] - Number of elements to choose from the set. 103 | * @returns {Generator} yields each combination as an array 104 | */ 105 | combination: function* combination(arr, size = arr.length) { 106 | let that = this 107 | let end = arr.length - 1 108 | let data = [] 109 | yield* combinationUtil(0, 0) 110 | function* combinationUtil(start, index) { 111 | if (index === size) { // Current combination is ready to be processed, yield it 112 | return yield that.clones ? data.slice() : data // .slice() is a JS idiom for shallow cloning an array 113 | } 114 | // replace index with all possible elements. The condition 115 | // "end - i + 1 >= size - index" makes sure that including one element 116 | // at index will make a combination with remaining elements 117 | // at remaining positions 118 | for (let i = start; i <= end && end - i + 1 >= size - index; i++) { 119 | data[index] = arr[i] 120 | yield* combinationUtil(i + 1, index + 1) 121 | } 122 | } 123 | }, 124 | 125 | /** 126 | * Generates all permutations of a set. 127 | * @param {Array|String} arr - The set of elements. 128 | * @param {Number} [size=arr.length] - Number of elements to choose from the set. 129 | * @returns {Generator} yields each permutation as an array 130 | */ 131 | permutation: function* permutation(arr, size = arr.length) { 132 | let that = this 133 | let len = arr.length 134 | if (size === len) { // switch to Heap's algorithm. it's more efficient 135 | return yield* heapsAlg(arr, that.clones) 136 | } 137 | let data = [] 138 | let indecesUsed = [] // permutations do not repeat elements. keep track of the indeces of the elements already used 139 | yield* permutationUtil(0) 140 | function* permutationUtil(index) { 141 | if (index === size) { 142 | return yield that.clones ? data.slice() : data 143 | } 144 | for (let i = 0; i < len; i++) { 145 | if (!indecesUsed[i]) { 146 | indecesUsed[i] = true 147 | data[index] = arr[i] 148 | yield *permutationUtil(index + 1) 149 | indecesUsed[i] = false 150 | } 151 | } 152 | } 153 | }, 154 | 155 | /** 156 | * Generates all possible subsets of a set (a.k.a. power set). 157 | * @param {Array|String} arr - The set of elements. 158 | * @returns {Generator} yields each subset as an array 159 | */ 160 | powerSet: function* powerSet(arr) { 161 | let that = this 162 | let len = arr.length 163 | let data = [] 164 | yield* powerUtil(0, 0) 165 | function* powerUtil(start, index) { 166 | data.length = index 167 | yield that.clones ? data.slice() : data 168 | if (index === len) { 169 | return 170 | } 171 | for (let i = start; i < len; i++) { 172 | data[index] = arr[i] 173 | yield* powerUtil(i + 1, index + 1) 174 | } 175 | } 176 | }, 177 | 178 | /** 179 | * Generates the permutation of the combinations of a set. 180 | * @param {Array|String} arr - The set of elements. 181 | * @returns {Generator} yields each permutation as an array 182 | */ 183 | permutationCombination: function* permutationCombination(arr) { 184 | let that = this 185 | let len = arr.length 186 | let data = [] 187 | let indecesUsed = [] 188 | yield* permutationUtil(0) 189 | function* permutationUtil(index) { 190 | data.length = index 191 | yield that.clones ? data.slice() : data 192 | if (index === len) { 193 | return 194 | } 195 | for (let i = 0; i < len; i++) { 196 | if (!indecesUsed[i]) { 197 | indecesUsed[i] = true 198 | data[index] = arr[i] 199 | yield *permutationUtil(index + 1) 200 | indecesUsed[i] = false 201 | } 202 | } 203 | } 204 | }, 205 | 206 | /** 207 | * Generates all possible "numbers" from the digits of a set. 208 | * @param {Array|String} arr - The set of digits. 209 | * @param {Number} [size=arr.length] - How many digits will be in the numbers. 210 | * @returns {Generator} yields all digits as an array 211 | */ 212 | baseN: function* baseN(arr, size = arr.length) { 213 | let that = this 214 | let len = arr.length 215 | let data = [] 216 | yield* baseNUtil(0) 217 | function* baseNUtil(index) { 218 | if (index === size) { 219 | return yield that.clones ? data.slice() : data 220 | } 221 | for (let i = 0; i < len; i++) { 222 | data[index] = arr[i] 223 | yield* baseNUtil(index + 1) 224 | } 225 | } 226 | }, 227 | 228 | /** 229 | * Infinite generator for all possible "numbers" from a set of digits. 230 | * @param {Array|String} arr - The set of digits 231 | * @returns {Generator} yields all digits as an array 232 | */ 233 | baseNAll: function* permutationAll(arr) { 234 | for (let len = 1; true; len++) { 235 | yield* this.baseN(arr, len) 236 | } 237 | }, 238 | 239 | /** 240 | * Generates the cartesian product of the sets. 241 | * @param {...(Array|String)} sets - variable number of sets of n elements. 242 | * @returns {Generator} yields each product as an array 243 | */ 244 | cartesian: function* cartesian(...sets) { 245 | let that = this 246 | let data = [] 247 | yield* cartesianUtil(0) 248 | function* cartesianUtil(index) { 249 | if (index === sets.length) { 250 | return yield that.clones ? data.slice() : data 251 | } 252 | for (let i = 0; i < sets[index].length; i++) { 253 | data[index] = sets[index][i] 254 | yield* cartesianUtil(index + 1) 255 | } 256 | } 257 | }, 258 | 259 | /** 260 | * Shuffles an array in place using the Fisher–Yates shuffle. 261 | * @param {Array} arr - A set of elements. 262 | * @returns {Array} a random, unbiased perutation of arr 263 | */ 264 | shuffle: function shuffle(arr) { 265 | for (let i = arr.length - 1; i > 0; i--) { 266 | let j = Math.floor(Math.random() * (i + 1)) 267 | swap(arr, i, j) 268 | } 269 | return arr 270 | } 271 | 272 | } 273 | 274 | 275 | let clone = { clones: true } 276 | clone.combination = G.combination 277 | clone.permutation = G.permutation 278 | clone.powerSet = G.powerSet 279 | clone.permutationCombination = G.permutationCombination 280 | clone.baseN = G.baseN 281 | clone.baseNAll = G.baseNAll 282 | clone.cartesian = G.cartesian 283 | 284 | G.clone = clone 285 | 286 | 287 | 288 | /* 289 | * More efficient alorithm for permutations of All elements in an array. Doesn't 290 | * work for "sub-permutations", e.g. permutations of 3 elements from [1, 2, 3, 4, 5] 291 | */ 292 | function* heapsAlg(arr, clone) { 293 | let size = arr.length 294 | if (typeof arr === 'string') { 295 | arr = arr.split('') 296 | } 297 | yield* heapsUtil(0) 298 | function* heapsUtil(index) { 299 | if (index === size) { 300 | return yield clone ? arr.slice() : arr 301 | } 302 | 303 | for (let j = index; j < size; j++) { 304 | swap(arr, index, j) 305 | yield* heapsUtil(index + 1) 306 | swap(arr, index, j) 307 | } 308 | } 309 | } 310 | 311 | /* 312 | * Swaps two array elements. 313 | */ 314 | function swap(arr, i, j) { 315 | let len = arr.length 316 | if (i >= len || j >= len) { 317 | console.warn('Swapping an array\'s elements past its length.') 318 | } 319 | let temp = arr[j] 320 | arr[j] = arr[i] 321 | arr[i] = temp 322 | return arr 323 | } 324 | 325 | 326 | return G 327 | 328 | })); -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 27 | 66 | 78 | 90 | 102 | 114 | 117 | 118 | 119 |