{ "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# RChain Python gRPC client " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- This notebook is available at http://j.mp/rchain-py-grpc-walk-through" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- github https://github.com/proof-media/rchain-grpc\n", "- pypi https://pypi.org/user/proof-media/" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Introduction" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### How to reproduce this demo\n", "\n", "- Interactive locally\n", "- Read-only mode on the web" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Locally on your workstation \n", "with Docker containers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```bash\n", "git clone https://github.com/proof-media/rchain-notebook.git\n", "cd rchain-notebook\n", "docker-compose up\n", "```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Then open http://localhost:8888" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "'prooflikesrchainalot'" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# password is set in the `.env` file\n", "# and shared to notebook container\n", "%env NOTEBOOK_PASSWORD" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Read only mode" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Through https://nbviewer.jupyter.org/\n", "\n", "- [link to notebook](https://github.com/proof-media/rchain-notebook/blob/testing/name-registry/notebooks/walk-through.ipynb)\n", "- [link to slides](https://nbviewer.jupyter.org/format/slides/github/proof-media/rchain-notebook/blob/testing%2Fname-registry/notebooks/walk-through.ipynb#/)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Proof platform\n", "\n", "![proof image](https://i0.wp.com/proofmedia.io/wp-content/uploads/2018/06/Default-Logo-copyxhdpi.png?resize=246%2C159&ssl=1)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Because Truth Matters**\n", "\n", "https://proofmedia.io/" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "> We are building a platform which leverages the wisdom of the crowds to establish truth." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- people vote in our platform on articles for being Mostly True/False\n", "- users bet tokens to rank their conviction \n", "- voting closes when we reach some parameters that are proven to make \"the crowd wise\"\n", "- tallying the vote will find out what the *majority* says\n", "- we use the blockchain to lock the tokens and provide cryptographic proofs that votes weren't tampered" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Rchain is needed to *register* tokens/hashes computed \n", "\n", "when each user votes" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Credits" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Our backend is based on `Python 3.7+` and `Django framework`" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- inspired by the official rchain/python snippet \n", "\n", "https://github.com/rchain/rchain/tree/dev/node-client\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- developed mainly by Mateusz (a.k.a. `beetleman`)\n", "\n", "https://github.com/proof-media/rchain-grpc/graphs/contributors" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- I'm Paolo - CTO @Proof\n", "- Pythonista \n", "- Python teacher using Jupyter Notebooks" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Roadmap and status" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "rchain-grpc (0.7.1) - python client to rchain gRPC\r\n" ] } ], "source": [ "! pip search rchain | grep -i grpc" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "* Up to version `0.0.10` -> code developed was tested with `RNode 0.6.x`\n", "* `0.7.x` releases are compatible with `RNode 0.7.x`\n", "* `0.8.x` releases will be compatible with `RNode 0.8.x`" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- Eval/Repl [not working](https://github.com/proof-media/rchain-grpc/issues/12) for gRPC missing definition\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- (near) future goal\n", "\n", "move the repo into `rchain` GitHub space if possible, see [issue](https://github.com/proof-media/rchain-grpc/issues/8)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Using the code" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Connecting" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "With current `docker-compose` for the notebook you are running a RNode *standalone* instance" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "# we have the OS NODE_NAME variable holding the other container name\n", "RNODE_HOST = %env NODE_NAME" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "/bin/sh: 1: apk: not found\r\n" ] } ], "source": [ "! apk add curl" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "RChain Node 0.7.1 (c3109d3bf326e91bf9bec7248ced8bad51e56d6b)" ] } ], "source": [ "! curl $RNODE_HOST:40403/version" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Now we can open a channel through `gRPC` against the RChain node \n", "\n", "using the Python library!" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "NOTE: in running docker image the package is already installed,\n", "\n", "while normally you would do:\n", "```bash\n", "pip install rchain-grpc\n", "```" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from rchain_grpc import casper\n", "\n", "connection = casper.create_connection(host=RNODE_HOST)\n", "connection" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Write Rholang code" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "In a notebook you can write a file like this" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Writing hello_world.rho\n" ] } ], "source": [ "%%file hello_world.rho\n", "\n", "new print(`rho:io:stdout`) in {\n", " print!(\"Hello World!\")\n", "}\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Then edit it inside the notebook server,\n", "e.g. link to file" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "# then read the file to use the code in python\n", "with open('hello_world.rho') as fh:\n", " rholang_code = fh.read()" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "# alternative: write directly the code with triple quoted strings\n", "rholang_code = \"\"\"\n", "new print(`rho:io:stdout`) in {\n", " print!(\"Hello World!\")\n", "}\n", "\"\"\"" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "new print(`rho:io:stdout`) in {\n", " print!(\"Hello World!\")\n", "}\n", "\n" ] } ], "source": [ "print(rholang_code)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Deploy and propose" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/plain": [ "{'success': True, 'message': 'Success!'}" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "casper.deploy(connection, rholang_code)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/plain": [ "{'success': True, 'message': 'Success! Block 65581493c0... created and added.'}" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "casper.propose(connection)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Now check logs of the rnode to see if we have `Hello World!` string" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Play with blocks" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/plain": [ "[{'blockHash': '65581493c0a1a47aa9f483a043b464a98f49527f6086fba4d0f0c876ccc0b5cf',\n", " 'blockSize': '1342',\n", " 'blockNumber': 1,\n", " 'version': 1,\n", " 'deployCount': 1,\n", " 'tupleSpaceHash': '477f7f0c469de6d500d8a1f74852a4ecf49df9a7fa463207d62258161bf39fb7',\n", " 'timestamp': 1541548724337,\n", " 'faultTolerance': -1.0,\n", " 'mainParentHash': '8e90e1071b1df8cb84ec0ab06847d5eb6b7e3f708a75b8e1301f3524b317abc7',\n", " 'parentsHashList': ['8e90e1071b1df8cb84ec0ab06847d5eb6b7e3f708a75b8e1301f3524b317abc7'],\n", " 'sender': 'eabe5a1a0750d2a8745709bb0bdb24f63c6a8ac3a887b9bed40b34b0598ddf08'}]" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "output = casper.get_blocks(connection, depth=1)\n", "\n", "# NOTE: protobuf outputs are always converted into Python dictionaries by our library\n", "output" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "'65581493c0a1a47aa9f483a043b464a98f49527f6086fba4d0f0c876ccc0b5cf'" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "block_hash = output.pop().get('blockHash')\n", "block_hash" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/plain": [ "{'blockHash': '65581493c0a1a47aa9f483a043b464a98f49527f6086fba4d0f0c876ccc0b5cf',\n", " 'blockSize': '1342',\n", " 'blockNumber': 1,\n", " 'version': 1,\n", " 'deployCount': 1,\n", " 'tupleSpaceHash': '477f7f0c469de6d500d8a1f74852a4ecf49df9a7fa463207d62258161bf39fb7',\n", " 'tupleSpaceDump': '@{Unforgeable(0xa50a17f94a9bf43206517f07ddcd76e64e8350533ad0b6715b0e559eac10b8dd)}!(`rho:id:dputnspi15oxxnyymjrpu7rkaok3bjkiwq84z7cqcrx4ktqfpyapn4`) |\\n@{Unforgeable(0x861583b3fab1a04eed7eeb4c03f53450a7cc12bd184944787b99b8f58b577a4d)}!({5122eac8a5c99b7da8f6d40d5f3269c6844dabde0418749ece2aeedc64c27703 : (288, \"secp256k1Verify\", Nil, 1), 5a3fff1ed432237e779fc6aa20d7549d043cc0dd92180ebee0346229598870f8 : (228, \"secp256k1Verify\", Nil, 2), d6b0c603a51fbcd56db1606a0591310876f93bdbf2309c7bdbc277a080368990 : (188, \"secp256k1Verify\", Nil, 4), a3158195b3ca6dfb88b8f0cb0788b01f25ea11421104df071bd043ca27f2def4 : (202, \"secp256k1Verify\", Nil, 3), e84b0ca96139b9c5e1a58b55e9d84682318a2030eaf24923204a1473ed659b34 : (224, \"secp256k1Verify\", Nil, 5), eabe5a1a0750d2a8745709bb0bdb24f63c6a8ac3a887b9bed40b34b0598ddf08 : (92, \"secp256k1Verify\", Nil, 6)}) |\\n@{Unforgeable(0xa4fd447dedfc960485983ee817632cf36d79f45fd1796019edfb4a84a81d1697)}!({1b : (0, 671159b596e0f788005a48d9f48ac41590a555a38fabf58e611fa545c56830, (9223372036854775807, bundle+ { Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406) }))}) |\\n@{Unforgeable(0x467b5b943fa7e4dac6532a75e43c4444038106a0a78fd0c7e4ea636e66b0724c)}!(1222) |\\n@{\"proofOfStake\"}!(Unforgeable(0xc03e6f8c2d4514bc3175636bc2da86f26785519124f2c4f7fe510518fa51134e)) |\\n@{Unforgeable(0xb6b18b8eb0deab2f97260fcade426fffd42d24e148f90786fdc6920c9ca67bb0)}!!(1) |\\nfor( @{x0} <= @{\"MakeMint\"} ) {\\n new x1, x2, x3 in {\\n @{x0}!(x1) |\\n for( @{x4}, @{x5} <= @{(x1, \"makePurse\")} ) {\\n new x6 in {\\n @{(\"MakeMint\", \"int2NN\")}!(x4, x6) |\\n for( @{x7} <- @{x6} ) {\\n @{x2}!(x7, x5)\\n }\\n }\\n } |\\n for( @{x4}, @{x5} <= @{x2} ) {\\n new x6 in {\\n @{x5}!(x6) |\\n for( @{x7}, @{x8}, @{x9} <= @{(x6, \"deposit\")} ) {\\n new x10 in {\\n @{(x8, x3)}!(x7, x10) |\\n for( @{x11} <- @{x10} ) {\\n match x11 {\\n true => @{(x4, \"add\")}!(x7, x9) ;\\n false => @{x9}!(false)\\n }\\n }\\n }\\n } |\\n for( @{x7} <= @{(x6, \"getBalance\")} ) {\\n @{(x4, \"value\")}!(x7)\\n } |\\n for( @{x7}, @{x8} <= @{(x6, \"split\")} ) {\\n new x9, x10 in {\\n @{(x6, \"sprout\")}!(x9) |\\n for( @{x11} <- @{x9} ) {\\n @{(x11, \"deposit\")}!(x7, x6, x10) |\\n for( @{x12} <- @{x10} ) {\\n match x12 {\\n true => @{x8}!([x11]) ;\\n false => @{x8}!([])\\n }\\n }\\n }\\n }\\n } |\\n for( @{x7} <= @{(x6, \"sprout\")} ) {\\n @{(x1, \"makePurse\")}!(0, x7)\\n } |\\n for( @{x7}, @{x8} <= @{(x6, x3)} ) {\\n @{(x4, \"sub\")}!(x7, x8)\\n }\\n }\\n }\\n }\\n} |\\nfor( @{x0}, @{x1} <= @{Unforgeable(0xf1a28850d52974f04a1088f49122954ac54ec420c1377af7c8e5ffed95dce291)} ) {\\n new x2, x3 in {\\n @{(x0, \"getBalance\")}!(x2) |\\n for( @{x4} <- @{x2} ) {\\n @{(x0, \"split\")}!(x4, x3) |\\n for( @{x5} <- @{x3} ) {\\n match x5 {\\n [] => @{x1}!((\"Left\", \"Could not extract funds from given purse\")) ;\\n [x6] => @{x1}!((\"Right\", (x6, x4)))\\n }\\n }\\n }\\n }\\n} |\\nfor( @{x0}, @{x1}, @{x2}, @{x3} <= @{\"BasicWallet\"} ) {\\n new x4 in {\\n for( @{x5} <- @{x4} ) {\\n match x5 {\\n [] => @{x3}!([]) ;\\n [x6] => new x7, x8, x9 in {\\n @{x9}!(-1) |\\n @{x3}!([x7]) |\\n for( @{x10}, @{x11}, @{x12} <= @{(x7, \"deposit\")} ) {\\n @{(x0, \"deposit\")}!(x10, x11, x12)\\n } |\\n for( @{x10} <= @{(x7, \"getBalance\")} ) {\\n @{(x0, \"getBalance\")}!(x10)\\n } |\\n for( @{x10} <= @{(x7, \"getNonce\")} ) {\\n for( @{x11} <- @{x9} ) {\\n @{x10}!(x11) |\\n @{x9}!(x11)\\n }\\n } |\\n for( @{x10}, @{x11}, @{x12}, @{x13}, @{x14} <= @{(x7, \"transfer\")} ) {\\n new x15 in {\\n @{x8}!(x11, x10, x13, x12, x15) |\\n for( @{x16} <- @{x15} ) {\\n match x16 {\\n true => new x17 in {\\n @{(x0, \"split\")}!(x10, x17) |\\n for( @{x18} <- @{x17} ) {\\n match x18 {\\n [] => @{x14}!(\"Overdraft\") ;\\n [x19] => @{x14}!(\"Success\") |\\n @{x13}!(x19)\\n }\\n }\\n } ;\\n false => @{x14}!(\"Invalid signature or nonce\")\\n }\\n }\\n }\\n } |\\n for( @{x10}, @{x11}, @{x12}, @{x13}, @{x14} <= @{x8} ) {\\n for( @{x15} <- @{x9} ) {\\n match (x10 == (x15 + 1)) {\\n true => new x16, x17 in {\\n @{\"blake2b256Hash\"}!(([x10, x11, x12]).toByteArray(), x17) |\\n for( @{x18} <- @{x17} ) {\\n @{x6}!(x18, (x13).hexToBytes(), (x2).hexToBytes(), x16) |\\n for( @{x19} <- @{x16} ) {\\n match x19 {\\n true => @{x14}!(true) |\\n @{x9}!(x10) ;\\n false => @{x14}!(false) |\\n @{x9}!(x15)\\n }\\n }\\n }\\n } ;\\n false => @{x14}!(false) |\\n @{x9}!(x15)\\n }\\n }\\n }\\n }\\n }\\n } |\\n match x1 {\\n \"ed25519\" => @{x4}!([\"ed25519Verify\"]) ;\\n \"secp256k1\" => @{x4}!([\"secp256k1Verify\"]) ;\\n _ => @{x4}!([])\\n }\\n }\\n} |\\nfor( @{x0} <= @{(Unforgeable(0x35de8d90c7ea0fe977da8e7fbc878e9f7cc7a33577352fc4338c0f494937c6b8), \"sprout\")} ) {\\n @{(Unforgeable(0xef54c68d487b5e6c72d4e8eae7543eb2f4fc243ade8e2360e8a077cbfa34da8d), \"makePurse\")}!(0, x0)\\n} |\\nfor( @{\"foreach\"}, @{x0}, @{x1}, @{x2} <= @{Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406)} ) {\\n new x3, x4 in {\\n @{Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406)}!(\"fold\", x0, Nil, x3, x4) |\\n for( @{_} <- @{x4} ) {\\n @{x2}!(true)\\n } |\\n for( @{x5}, @{x6}, @{x7} <= @{x3} ) {\\n new x8 in {\\n @{x1}!(x5, x8) |\\n for( @{_} <- @{x8} ) {\\n @{x7}!(Nil)\\n }\\n }\\n }\\n }\\n} |\\nfor( @{\"append\"}, @{x0}, @{x1}, @{x2} <= @{Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406)} ) {\\n @{x2}!((x0 ++ [x1]))\\n} |\\nfor( @{\"zip\"}, @{x0}, @{x1}, @{x2} <= @{Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406)} ) {\\n new x3 in {\\n @{x3}!((x0, x1), [], x2) |\\n for( @{x4}, @{x5}, @{x6} <= @{x3} ) {\\n match x4 {\\n ([x8...x7], [x10...x9]) => @{x3}!((x7, x9), (x5 ++ [(x8, x10)]), x6) ;\\n _ => @{x6}!(x5)\\n }\\n }\\n }\\n} |\\nfor( @{\"fold\"}, @{x0}, @{x1}, @{x2}, @{x3} <= @{Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406)} ) {\\n new x4 in {\\n for( @{x5}, @{x6}, @{x7} <= @{x4} ) {\\n new x8 in {\\n @{x2}!(x5, x6, x8) |\\n for( @{x9} <- @{x8} ) {\\n @{x7}!(false, x9)\\n }\\n }\\n } |\\n new x5 in {\\n @{Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406)}!(\"partialFold\", x0, x1, x4, x5) |\\n for( @{_}, @{x6} <- @{x5} ) {\\n @{x3}!(x6)\\n }\\n }\\n }\\n} |\\nfor( @{\"indexOf\"}, @{x0}, @{x1}, @{x2} <= @{Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406)} ) {\\n new x3 in {\\n for( @{x4}, @{x5}, @{x6} <= @{x3} ) {\\n @{x6}!((x4 == x1), (x5 + 1))\\n } |\\n new x4 in {\\n @{Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406)}!(\"partialFold\", x0, -1, x3, x4) |\\n for( @{x5}, @{x6} <- @{x4} ) {\\n match x5 {\\n true => @{x2}!(x6) ;\\n false => @{x2}!(-1)\\n }\\n }\\n }\\n }\\n} |\\nfor( @{\"parMap\"}, @{x0}, @{x1}, @{x2} <= @{Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406)} ) {\\n new x3, x4, x5 in {\\n @{Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406)}!(\"map\", x0, x4, x3) |\\n for( @{x6} <- @{x3} ) {\\n @{Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406)}!(\"map\", x6, x5, x2)\\n } |\\n for( @{x6}, @{x7} <= @{x5} ) {\\n for( @{x8} <- @{x6} ) {\\n @{x7}!(x8)\\n }\\n } |\\n for( @{x6}, @{x7} <= @{x4} ) {\\n new x8 in {\\n @{x7}!(x8) |\\n @{x1}!(x6, x8)\\n }\\n }\\n }\\n} |\\nfor( @{\"unorderedParMap\"}, @{x0}, @{x1}, @{x2} <= @{Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406)} ) {\\n new x3, x4, x5, x6, x7 in {\\n for( @{x8} <= @{x4} ) {\\n for( @{x9} <- @{x7} ; @{x10} <- @{x6} ; @{x11} <- @{x5} ) {\\n @{x5}!(x11) |\\n match (x11 == (x10 + 1)) {\\n true => @{Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406)}!(\"prepend\", x8, x9, x2) ;\\n false => @{x6}!((x10 + 1)) |\\n @{Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406)}!(\"prepend\", x8, x9, x7)\\n }\\n }\\n } |\\n for( @{x8}, @{x9} <= @{x3} ) {\\n match x8 {\\n [x11...x10] => new x12 in {\\n @{x3}!(x10, (x9 + 1)) |\\n @{x1}!(x11, x12) |\\n for( @{x13} <- @{x12} ) {\\n @{x4}!(x13)\\n }\\n } ;\\n _ => @{x5}!(x9)\\n }\\n } |\\n match x0 {\\n [] => @{x2}!([]) ;\\n _ => @{x7}!([]) |\\n @{x6}!(0) |\\n @{x3}!(x0, 0)\\n }\\n }\\n} |\\nfor( @{\"map\"}, @{x0}, @{x1}, @{x2} <= @{Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406)} ) {\\n new x3 in {\\n @{Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406)}!(\"fold\", x0, [], x3, x2) |\\n for( @{x4}, @{x5}, @{x6} <= @{x3} ) {\\n new x7 in {\\n @{x1}!(x4, x7) |\\n for( @{x8} <- @{x7} ) {\\n @{Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406)}!(\"append\", x5, x8, x6)\\n }\\n }\\n }\\n }\\n} |\\nfor( @{\"reverse\"}, @{x0}, @{x1} <= @{Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406)} ) {\\n new x2 in {\\n @{Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406)}!(\"fold\", x0, [], x2, x1) |\\n for( @{x3}, @{x4}, @{x5} <= @{x2} ) {\\n @{Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406)}!(\"prepend\", x3, x4, x5)\\n }\\n }\\n} |\\nfor( @{\"prepend\"}, @{x0}, @{x1}, @{x2} <= @{Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406)} ) {\\n @{x2}!(([x0] ++ x1))\\n} |\\nfor( @{\"range\"}, @{x0}, @{x1}, @{x2} <= @{Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406)} ) {\\n new x3 in {\\n @{x3}!((x1 - 1), []) |\\n for( @{x4}, @{x5} <= @{x3} ) {\\n match (x4 < x0) {\\n true => @{x2}!(x5) ;\\n false => @{x3}!((x4 - 1), ([x4] ++ x5))\\n }\\n }\\n }\\n} |\\nfor( @{\"partialFold\"}, @{x0}, @{x1}, @{x2}, @{x3} <= @{Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406)} ) {\\n new x4 in {\\n @{x4}!(x1, x0) |\\n for( @{x5}, @{x6} <= @{x4} ) {\\n match x6 {\\n [x8...x7] => new x9 in {\\n @{x2}!(x8, x5, x9) |\\n for( @{x10}, @{x11} <- @{x9} ) {\\n match x10 {\\n true => @{x3}!(x10, x11) ;\\n false => @{x4}!(x11, x7)\\n }\\n }\\n } ;\\n _ => @{x3}!(false, x5)\\n }\\n }\\n }\\n} |\\nfor( @{x0}, @{x1} <= @{\"blake2b256Hash\"} ) {\\n Nil\\n} |\\nfor( @{x0} <= @{Unforgeable(0x00)} ) {\\n Nil\\n} |\\nfor( @{x0}, @{x1} <= @{(Unforgeable(0xef54c68d487b5e6c72d4e8eae7543eb2f4fc243ade8e2360e8a077cbfa34da8d), \"makePurse\")} ) {\\n new x2 in {\\n @{(\"MakeMint\", \"int2NN\")}!(x0, x2) |\\n for( @{x3} <- @{x2} ) {\\n @{Unforgeable(0x93120564b1dd78436be5c0c365960428776d831d82d2cd354e852d16d9b3a280)}!(x3, x1)\\n }\\n }\\n} |\\nfor( @{x0} <= @{(Unforgeable(0xc03e6f8c2d4514bc3175636bc2da86f26785519124f2c4f7fe510518fa51134e), \"getBonds\")} ) {\\n for( @{x1} <- @{Unforgeable(0x861583b3fab1a04eed7eeb4c03f53450a7cc12bd184944787b99b8f58b577a4d)} ) {\\n @{x0}!(x1) |\\n @{Unforgeable(0x861583b3fab1a04eed7eeb4c03f53450a7cc12bd184944787b99b8f58b577a4d)}!(x1)\\n }\\n} |\\nfor( @{x0}, @{x1} <= @{(Unforgeable(0x85d832a5f562a1bbf273b98ab17279f6169a157dd89d5417d4d3dfbd78ff5269), \"add\")} ) {\\n match (x0 >= 0) {\\n true => for( @{x2} <- @{Unforgeable(0x467b5b943fa7e4dac6532a75e43c4444038106a0a78fd0c7e4ea636e66b0724c)} ) {\\n match ((x2 + x0) > x2) {\\n true => @{x1}!(true) |\\n @{Unforgeable(0x467b5b943fa7e4dac6532a75e43c4444038106a0a78fd0c7e4ea636e66b0724c)}!((x2 + x0)) ;\\n false => @{x1}!(false) |\\n @{Unforgeable(0x467b5b943fa7e4dac6532a75e43c4444038106a0a78fd0c7e4ea636e66b0724c)}!(x2)\\n }\\n } ;\\n false => @{x1}!(false)\\n }\\n} |\\nfor( @{x0}, @{x1} <= @{\"BasicWalletFaucet\"} ) {\\n new x2 in {\\n @{x1}!(x2) |\\n for( @{x3}, @{x4}, @{x5}, @{x6} <= @{x2} ) {\\n new x7 in {\\n @{(x0, \"makePurse\")}!(x3, x7) |\\n for( @{x8} <- @{x7} ) {\\n @{\"BasicWallet\"}!(x8, x4, x5, x6)\\n }\\n }\\n }\\n }\\n} |\\nfor( @{x0}, @{x1} <= @{(Unforgeable(0xc03e6f8c2d4514bc3175636bc2da86f26785519124f2c4f7fe510518fa51134e), \"validateBondingRate\")} ) {\\n @{x1}!((\"Right\", x0))\\n} |\\nfor( @{x0}, @{x1} <= @{Unforgeable(0x03)} ) {\\n Nil\\n} |\\nfor( @{x0}, @{x1} <= @{\"NonNegativeNumber\"} ) {\\n new x2, x3 in {\\n @{x1}!(x2) |\\n for( @{x4}, @{x5} <= @{(x2, \"add\")} ) {\\n match (x4 >= 0) {\\n true => for( @{x6} <- @{x3} ) {\\n match ((x6 + x4) > x6) {\\n true => @{x5}!(true) |\\n @{x3}!((x6 + x4)) ;\\n false => @{x5}!(false) |\\n @{x3}!(x6)\\n }\\n } ;\\n false => @{x5}!(false)\\n }\\n } |\\n for( @{x4}, @{x5} <= @{(x2, \"sub\")} ) {\\n match (x4 >= 0) {\\n true => for( @{x6} <- @{x3} ) {\\n match (x4 <= x6) {\\n true => @{x5}!(true) |\\n @{x3}!((x6 - x4)) ;\\n false => @{x5}!(false) |\\n @{x3}!(x6)\\n }\\n } ;\\n false => @{x5}!(false)\\n }\\n } |\\n for( @{x4} <= @{(x2, \"value\")} ) {\\n for( @{x5} <- @{x3} ) {\\n @{x4}!(x5) |\\n @{x3}!(x5)\\n }\\n } |\\n match (x0 >= 0) {\\n true => @{x3}!(x0) ;\\n _ => @{x3}!(0)\\n }\\n }\\n} |\\nfor( @{x0}, @{x1} <= @{(\"WalletCheck\", \"create\")} ) {\\n new x2 in {\\n @{x2}!(false) |\\n for( @{[x3, x4]}, @{x5} <= @{x0} ) {\\n for( @{x6} <- @{x2} ) {\\n match x6 {\\n true => @{x4}!([false, \"Already claimed wallet\"]) |\\n @{x2}!(x6) ;\\n false => new x7, x8, x9 in {\\n @{\"keccak256Hash\"}!(([x3, x4]).toByteArray(), x9) |\\n for( @{x10} <- @{x9} ) {\\n @{\"secp256k1Verify\"}!(x10, (x5).hexToBytes(), ((\"04\" ++ x3)).hexToBytes(), x7) |\\n for( @{x11} <- @{x7} ) {\\n match x11 {\\n true => @{(\"WalletCheck\", \"publicToAddr\")}!(x3, x8) |\\n for( @{x12} <- @{x8} ) {\\n match (x12 == ((x0).slice(2,(x0).length())).hexToBytes()) {\\n true => new x13 in {\\n @{\"BasicWallet\"}!(x1, \"secp256k1\", (\"04\" ++ x3), x13) |\\n @{x2}!(true) |\\n for( @{[x14]} <- @{x13} ) {\\n @{x4}!([true, x14]) |\\n @{x3}!!(x14)\\n }\\n } ;\\n false => @{x4}!([false, \"Public key is not the preimage of hash\"]) |\\n @{x2}!(x6)\\n }\\n } ;\\n false => @{x4}!([false, \"Signature verification failed\"]) |\\n @{x2}!(x6)\\n }\\n }\\n }\\n }\\n }\\n }\\n }\\n }\\n} |\\nfor( @{x0}, @{x1}, @{x2}, @{x3} <= @{\"secp256k1Verify\"} ) {\\n Nil\\n} |\\nfor( @{x0}, @{x1} <= @{(Unforgeable(0x85d832a5f562a1bbf273b98ab17279f6169a157dd89d5417d4d3dfbd78ff5269), \"sub\")} ) {\\n match (x0 >= 0) {\\n true => for( @{x2} <- @{Unforgeable(0x467b5b943fa7e4dac6532a75e43c4444038106a0a78fd0c7e4ea636e66b0724c)} ) {\\n match (x0 <= x2) {\\n true => @{x1}!(true) |\\n @{Unforgeable(0x467b5b943fa7e4dac6532a75e43c4444038106a0a78fd0c7e4ea636e66b0724c)}!((x2 - x0)) ;\\n false => @{x1}!(false) |\\n @{Unforgeable(0x467b5b943fa7e4dac6532a75e43c4444038106a0a78fd0c7e4ea636e66b0724c)}!(x2)\\n }\\n } ;\\n false => @{x1}!(false)\\n }\\n} |\\nfor( @{x0}, @{x1}, @{x2} <= @{Unforgeable(0xa6ba2f5c0f8e6965dd85796d311067882a2918073fecb54e2facf49ae4746a14)} ) {\\n new x3, x4, x5, x6, x7, x8 in {\\n @{bundle+ { Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406) }}!(\"range\", 1, (x0 + 1), x3) |\\n for( @{x9} <- @{x3} ) {\\n @{bundle+ { Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406) }}!(\"map\", x9, x4, x5) |\\n for( @{x10} <- @{x5} ) {\\n @{bundle+ { Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406) }}!(\"fold\", x10, 0, x6, x8) |\\n for( @{x11} <- @{x8} ) {\\n @{x2}!(([(((x10).nth(0) + x1) - x11)] ++ (x10).slice(1,x0)))\\n }\\n }\\n } |\\n for( @{x9}, @{x10}, @{x11} <= @{x6} ) {\\n @{x11}!((x9 + x10))\\n } |\\n for( @{x9}, @{x10} <= @{x4} ) {\\n @{x10}!((2 * x1) * ((x0 + 1) - x9) / (x0 * (x0 + 1)))\\n }\\n }\\n} |\\nfor( @{x0} <= @{(\"Rev\", \"makePurse\")} ) {\\n @{(Unforgeable(0xef54c68d487b5e6c72d4e8eae7543eb2f4fc243ade8e2360e8a077cbfa34da8d), \"makePurse\")}!(0, x0)\\n} |\\nfor( @{x0}, @{x1}, @{x2}, @{x3} <= @{Unforgeable(0x0b)} ) {\\n Nil\\n} |\\nfor( @{x0}, @{x1}, @{x2} <= @{(\"Either\", \"compose\")} ) {\\n new x3 in {\\n @{bundle+ { Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406) }}!(\"fold\", x1, (\"Right\", x0), x3, x2) |\\n for( @{x4}, @{x5}, @{x6} <= @{x3} ) {\\n @{(\"Either\", \"flatMap\")}!(x5, x4, x6)\\n }\\n }\\n} |\\nfor( @{x0}, @{x1} <= @{Unforgeable(0x93120564b1dd78436be5c0c365960428776d831d82d2cd354e852d16d9b3a280)} ) {\\n new x2 in {\\n @{x1}!(x2) |\\n for( @{x3}, @{x4}, @{x5} <= @{(x2, \"deposit\")} ) {\\n new x6 in {\\n @{(x4, Unforgeable(0xb4deb00d3e6005335f0e7593fed8f43a6c672456b9d86594edc2ed52f46c73c7))}!(x3, x6) |\\n for( @{x7} <- @{x6} ) {\\n match x7 {\\n true => @{(x0, \"add\")}!(x3, x5) ;\\n false => @{x5}!(false)\\n }\\n }\\n }\\n } |\\n for( @{x3} <= @{(x2, \"getBalance\")} ) {\\n @{(x0, \"value\")}!(x3)\\n } |\\n for( @{x3}, @{x4} <= @{(x2, \"split\")} ) {\\n new x5, x6 in {\\n @{(x2, \"sprout\")}!(x5) |\\n for( @{x7} <- @{x5} ) {\\n @{(x7, \"deposit\")}!(x3, x2, x6) |\\n for( @{x8} <- @{x6} ) {\\n match x8 {\\n true => @{x4}!([x7]) ;\\n false => @{x4}!([])\\n }\\n }\\n }\\n }\\n } |\\n for( @{x3} <= @{(x2, \"sprout\")} ) {\\n @{(Unforgeable(0xef54c68d487b5e6c72d4e8eae7543eb2f4fc243ade8e2360e8a077cbfa34da8d), \"makePurse\")}!(0, x3)\\n } |\\n for( @{x3}, @{x4} <= @{(x2, Unforgeable(0xb4deb00d3e6005335f0e7593fed8f43a6c672456b9d86594edc2ed52f46c73c7))} ) {\\n @{(x0, \"sub\")}!(x3, x4)\\n }\\n }\\n} |\\nfor( @{x0} <= @{(Unforgeable(0x35de8d90c7ea0fe977da8e7fbc878e9f7cc7a33577352fc4338c0f494937c6b8), \"getBalance\")} ) {\\n @{(Unforgeable(0x85d832a5f562a1bbf273b98ab17279f6169a157dd89d5417d4d3dfbd78ff5269), \"value\")}!(x0)\\n} |\\nfor( @{x0}, @{x1} <= @{(Unforgeable(0x35de8d90c7ea0fe977da8e7fbc878e9f7cc7a33577352fc4338c0f494937c6b8), Unforgeable(0xb4deb00d3e6005335f0e7593fed8f43a6c672456b9d86594edc2ed52f46c73c7))} ) {\\n @{(Unforgeable(0x85d832a5f562a1bbf273b98ab17279f6169a157dd89d5417d4d3dfbd78ff5269), \"sub\")}!(x0, x1)\\n} |\\nfor( @{x0}, @{x1} <= @{(Unforgeable(0xc03e6f8c2d4514bc3175636bc2da86f26785519124f2c4f7fe510518fa51134e), \"validateBondAmount\")} ) {\\n new x2 in {\\n @{(x0, \"getBalance\")}!(x2) |\\n for( @{x3} <- @{x2} ; @{x4} <- @{Unforgeable(0xb6b18b8eb0deab2f97260fcade426fffd42d24e148f90786fdc6920c9ca67bb0)} ) {\\n match ((x3 - x4) < 1) {\\n true => @{x1}!((\"Left\", \"Bond less than minimum!\")) ;\\n false => match ((x3 - x4) > 9223372036854775807) {\\n true => @{x1}!((\"Left\", \"Bond greater than maximum!\")) ;\\n false => @{x1}!((\"Right\", x0))\\n }\\n }\\n }\\n }\\n} |\\nfor( @{x0}, @{x1}, @{x2} <= @{(\"Either\", \"map\")} ) {\\n match x0 {\\n (\"Right\", x3) => new x4 in {\\n @{x1}!(x3, x4) |\\n for( @{x5} <- @{x4} ) {\\n @{x2}!((\"Right\", x5))\\n }\\n } ;\\n (\"Left\", _) => @{x2}!(x0)\\n }\\n} |\\nfor( @{x0}, @{x1}, @{x2}, @{x3}, @{x4} <= @{Unforgeable(0xf70b79534a11e1368f113641786a9a25a0af7b409a025d9c41bc8b21c0e49084)} ) {\\n new x5, x6, x7 in {\\n for( @{x8} <- @{Unforgeable(0xb6b18b8eb0deab2f97260fcade426fffd42d24e148f90786fdc6920c9ca67bb0)} ; @{x9} <- @{Unforgeable(0x861583b3fab1a04eed7eeb4c03f53450a7cc12bd184944787b99b8f58b577a4d)} ) {\\n @{Unforgeable(0xa6ba2f5c0f8e6965dd85796d311067882a2918073fecb54e2facf49ae4746a14)}!((x9).size(), x8, x5) |\\n for( @{x10} <- @{x5} ) {\\n @{x6}!(x9, x10, {}, x7) |\\n for( @{x11} <- @{x7} ) {\\n @{x4}!((true, \"Bond successful!\")) |\\n @{Unforgeable(0x861583b3fab1a04eed7eeb4c03f53450a7cc12bd184944787b99b8f58b577a4d)}!((x11).set(x0,((x2 - x8), x1, x3, ((x9).size() + 1))))\\n }\\n }\\n } |\\n for( @{x8}, @{x9}, @{x10}, @{x11} <= @{x6} ) {\\n match x8 {\\n {x13 : (x14, x15, x16, x17)...x12} => @{x6}!(x12, x9, (x10).set(x13,((x14 + (x9).nth((x17 - 1))), x15, x16, x17)), x11) ;\\n _ => @{x11}!(x10)\\n }\\n }\\n }\\n} |\\nfor( @{x0} <= @{Unforgeable(0x02)} ) {\\n Nil\\n} |\\nfor( @{x0} <= @{(Unforgeable(0x85d832a5f562a1bbf273b98ab17279f6169a157dd89d5417d4d3dfbd78ff5269), \"value\")} ) {\\n for( @{x1} <- @{Unforgeable(0x467b5b943fa7e4dac6532a75e43c4444038106a0a78fd0c7e4ea636e66b0724c)} ) {\\n @{x0}!(x1) |\\n @{Unforgeable(0x467b5b943fa7e4dac6532a75e43c4444038106a0a78fd0c7e4ea636e66b0724c)}!(x1)\\n }\\n} |\\nfor( @{x0}, @{x1} <= @{Unforgeable(0x09)} ) {\\n Nil\\n} |\\nfor( @{x0}, @{x1} <= @{(\"MakeMint\", \"int2NN\")} ) {\\n new x2 in {\\n @{\"NonNegativeNumber\"}!(x0, x2) |\\n for( @{x3} <- @{x2} ) {\\n @{x1}!(x3)\\n }\\n }\\n} |\\nfor( @{x0}, @{x1}, @{x2} <= @{(\"Either\", \"flatMap\")} ) {\\n match x0 {\\n (\"Right\", x3) => @{x1}!(x3, x2) ;\\n (\"Left\", _) => @{x2}!(x0)\\n }\\n} |\\nfor( @{x0}, @{x1} <= @{\"sha256Hash\"} ) {\\n Nil\\n} |\\nfor( @{x0}, @{x1} <= @{Unforgeable(0x01)} ) {\\n Nil\\n} |\\nfor( @{x0}, @{x1} <= @{(\"WalletCheck\", \"publicToAddr\")} ) {\\n new x2 in {\\n @{\"keccak256Hash\"}!((x0).hexToBytes(), x2) |\\n for( @{x3} <- @{x2} ) {\\n @{x1}!((x3).slice(12,32))\\n }\\n }\\n} |\\nfor( @{x0}, @{x1}, @{x2} <= @{(Unforgeable(0x35de8d90c7ea0fe977da8e7fbc878e9f7cc7a33577352fc4338c0f494937c6b8), \"deposit\")} ) {\\n new x3 in {\\n @{(x1, Unforgeable(0xb4deb00d3e6005335f0e7593fed8f43a6c672456b9d86594edc2ed52f46c73c7))}!(x0, x3) |\\n for( @{x4} <- @{x3} ) {\\n match x4 {\\n true => @{(Unforgeable(0x85d832a5f562a1bbf273b98ab17279f6169a157dd89d5417d4d3dfbd78ff5269), \"add\")}!(x0, x2) ;\\n false => @{x2}!(false)\\n }\\n }\\n }\\n} |\\nfor( @{x0}, @{x1}, @{x2} <= @{Unforgeable(0xa72b35dac1575b3d0bf066daaa32d92a5c4cb0392fe80506200aba8b1ba1006e)} ) {\\n new x3 in {\\n @{(Unforgeable(0x35de8d90c7ea0fe977da8e7fbc878e9f7cc7a33577352fc4338c0f494937c6b8), \"deposit\")}!(x1, x0, x3) |\\n for( @{x4} <- @{x3} ) {\\n match x4 {\\n true => @{x2}!((\"Right\", x0)) ;\\n false => @{x2}!((\"Left\", \"Deposit failed.\"))\\n }\\n }\\n }\\n} |\\nfor( @{x0}, @{x1} <= @{Unforgeable(0x0a)} ) {\\n Nil\\n} |\\nfor( @{x0}, @{x1} <= @{(Unforgeable(0x35de8d90c7ea0fe977da8e7fbc878e9f7cc7a33577352fc4338c0f494937c6b8), \"split\")} ) {\\n new x2, x3 in {\\n @{(Unforgeable(0x35de8d90c7ea0fe977da8e7fbc878e9f7cc7a33577352fc4338c0f494937c6b8), \"sprout\")}!(x2) |\\n for( @{x4} <- @{x2} ) {\\n @{(x4, \"deposit\")}!(x0, Unforgeable(0x35de8d90c7ea0fe977da8e7fbc878e9f7cc7a33577352fc4338c0f494937c6b8), x3) |\\n for( @{x5} <- @{x3} ) {\\n match x5 {\\n true => @{x1}!([x4]) ;\\n false => @{x1}!([])\\n }\\n }\\n }\\n }\\n} |\\nfor( @{x0}, @{x1}, @{x2}, @{x3}, @{x4} <= @{(Unforgeable(0xc03e6f8c2d4514bc3175636bc2da86f26785519124f2c4f7fe510518fa51134e), \"bond\")} ) {\\n new x5, x6, x7, x8 in {\\n @{Unforgeable(0xf1a28850d52974f04a1088f49122954ac54ec420c1377af7c8e5ffed95dce291)}!(x2, x6) |\\n for( @{x9}, @{x10} <- @{x7} ) {\\n new x11 in {\\n @{(Unforgeable(0xc03e6f8c2d4514bc3175636bc2da86f26785519124f2c4f7fe510518fa51134e), \"isBonded\")}!(x0, x11) |\\n for( @{x12} <- @{x11} ) {\\n match x12 {\\n true => @{x10}!((\"Left\", (\"Public key ${pk} already bonded.\" %% {\"pk\" : x0}))) ;\\n false => @{x10}!((\"Right\", x9))\\n }\\n }\\n }\\n } |\\n for( @{x9} <- @{x6} ) {\\n match x9 {\\n (\"Right\", (x10, x11)) => @{(\"Either\", \"compose\")}!(x10, [(Unforgeable(0xc03e6f8c2d4514bc3175636bc2da86f26785519124f2c4f7fe510518fa51134e), \"validateBondAmount\"), (Unforgeable(0xc03e6f8c2d4514bc3175636bc2da86f26785519124f2c4f7fe510518fa51134e), \"validateBondingRate\"), x7, x8], x5) |\\n for( @{_}, @{x12} <- @{x8} ) {\\n @{Unforgeable(0xa72b35dac1575b3d0bf066daaa32d92a5c4cb0392fe80506200aba8b1ba1006e)}!(x10, x11, x12)\\n } |\\n for( @{x12} <- @{x5} ) {\\n match x12 {\\n (\"Right\", _) => @{Unforgeable(0xf70b79534a11e1368f113641786a9a25a0af7b409a025d9c41bc8b21c0e49084)}!(x0, x1, x11, x3, x4) ;\\n (\"Left\", x13) => @{(x2, \"deposit\")}!(x11, x10, x5) |\\n for( @{_} <- @{x5} ) {\\n @{x4}!((false, x13))\\n }\\n }\\n } ;\\n (\"Left\", x10) => @{x4}!((false, x10))\\n }\\n }\\n }\\n} |\\nfor( @{x0}, @{x1} <= @{(Unforgeable(0xc03e6f8c2d4514bc3175636bc2da86f26785519124f2c4f7fe510518fa51134e), \"isBonded\")} ) {\\n for( @{x2} <- @{Unforgeable(0x861583b3fab1a04eed7eeb4c03f53450a7cc12bd184944787b99b8f58b577a4d)} ) {\\n @{x1}!((x2).contains(x0)) |\\n @{Unforgeable(0x861583b3fab1a04eed7eeb4c03f53450a7cc12bd184944787b99b8f58b577a4d)}!(x2)\\n }\\n} |\\nfor( @{x0}, @{x1}, @{x2}, @{x3}, @{x4} <= @{\"MakePoS\"} ) {\\n new x5, x6, x7, x8, x9, x10, x11 in {\\n @{x6}!(x3) |\\n @{x4}!(x5) |\\n @{x7}!!(x1) |\\n for( @{x12}, @{x13}, @{x14}, @{x15}, @{x16} <= @{(x5, \"bond\")} ) {\\n new x17, x18, x19, x20 in {\\n @{x8}!(x14, x18) |\\n for( @{x21}, @{x22} <- @{x19} ) {\\n new x23 in {\\n @{(x5, \"isBonded\")}!(x12, x23) |\\n for( @{x24} <- @{x23} ) {\\n match x24 {\\n true => @{x22}!((\"Left\", (\"Public key ${pk} already bonded.\" %% {\"pk\" : x12}))) ;\\n false => @{x22}!((\"Right\", x21))\\n }\\n }\\n }\\n } |\\n for( @{x21} <- @{x18} ) {\\n match x21 {\\n (\"Right\", (x22, x23)) => @{(\"Either\", \"compose\")}!(x22, [(x5, \"validateBondAmount\"), (x5, \"validateBondingRate\"), x19, x20], x17) |\\n for( @{_}, @{x24} <- @{x20} ) {\\n @{x9}!(x22, x23, x24)\\n } |\\n for( @{x24} <- @{x17} ) {\\n match x24 {\\n (\"Right\", _) => @{x10}!(x12, x13, x23, x15, x16) ;\\n (\"Left\", x25) => @{(x14, \"deposit\")}!(x23, x22, x17) |\\n for( @{_} <- @{x17} ) {\\n @{x16}!((false, x25))\\n }\\n }\\n } ;\\n (\"Left\", x22) => @{x16}!((false, x22))\\n }\\n }\\n }\\n } |\\n for( @{x12} <= @{(x5, \"getBonds\")} ) {\\n for( @{x13} <- @{x6} ) {\\n @{x12}!(x13) |\\n @{x6}!(x13)\\n }\\n } |\\n for( @{x12}, @{x13} <= @{(x5, \"isBonded\")} ) {\\n for( @{x14} <- @{x6} ) {\\n @{x13}!((x14).contains(x12)) |\\n @{x6}!(x14)\\n }\\n } |\\n for( @{x12}, @{x13} <= @{(x5, \"validateBondAmount\")} ) {\\n new x14 in {\\n @{(x12, \"getBalance\")}!(x14) |\\n for( @{x15} <- @{x14} ; @{x16} <- @{x7} ) {\\n match ((x15 - x16) < x1) {\\n true => @{x13}!((\"Left\", \"Bond less than minimum!\")) ;\\n false => match ((x15 - x16) > x2) {\\n true => @{x13}!((\"Left\", \"Bond greater than maximum!\")) ;\\n false => @{x13}!((\"Right\", x12))\\n }\\n }\\n }\\n }\\n } |\\n for( @{x12}, @{x13} <= @{(x5, \"validateBondingRate\")} ) {\\n @{x13}!((\"Right\", x12))\\n } |\\n for( @{x12}, @{x13}, @{x14} <= @{x11} ) {\\n new x15, x16, x17, x18, x19, x20 in {\\n @{bundle+ { Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406) }}!(\"range\", 1, (x12 + 1), x15) |\\n for( @{x21} <- @{x15} ) {\\n @{bundle+ { Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406) }}!(\"map\", x21, x16, x17) |\\n for( @{x22} <- @{x17} ) {\\n @{bundle+ { Unforgeable(0x6df7905a81f51e556695f3cbeccd1a81ffa1f3ab4c0884d18324d709cc8ea406) }}!(\"fold\", x22, 0, x18, x20) |\\n for( @{x23} <- @{x20} ) {\\n @{x14}!(([(((x22).nth(0) + x13) - x23)] ++ (x22).slice(1,x12)))\\n }\\n }\\n } |\\n for( @{x21}, @{x22}, @{x23} <= @{x18} ) {\\n @{x23}!((x21 + x22))\\n } |\\n for( @{x21}, @{x22} <= @{x16} ) {\\n @{x22}!((2 * x13) * ((x12 + 1) - x21) / (x12 * (x12 + 1)))\\n }\\n }\\n } |\\n for( @{x12}, @{x13}, @{x14}, @{x15}, @{x16} <= @{x10} ) {\\n new x17, x18, x19 in {\\n for( @{x20} <- @{x7} ; @{x21} <- @{x6} ) {\\n @{x11}!((x21).size(), x20, x17) |\\n for( @{x22} <- @{x17} ) {\\n @{x18}!(x21, x22, {}, x19) |\\n for( @{x23} <- @{x19} ) {\\n @{x16}!((true, \"Bond successful!\")) |\\n @{x6}!((x23).set(x12,((x14 - x20), x13, x15, ((x21).size() + 1))))\\n }\\n }\\n } |\\n for( @{x20}, @{x21}, @{x22}, @{x23} <= @{x18} ) {\\n match x20 {\\n {x25 : (x26, x27, x28, x29)...x24} => @{x18}!(x24, x21, (x22).set(x25,((x26 + (x21).nth((x29 - 1))), x27, x28, x29)), x23) ;\\n _ => @{x23}!(x22)\\n }\\n }\\n }\\n } |\\n for( @{x12}, @{x13}, @{x14} <= @{x9} ) {\\n new x15 in {\\n @{(x0, \"deposit\")}!(x13, x12, x15) |\\n for( @{x16} <- @{x15} ) {\\n match x16 {\\n true => @{x14}!((\"Right\", x12)) ;\\n false => @{x14}!((\"Left\", \"Deposit failed.\"))\\n }\\n }\\n }\\n } |\\n for( @{x12}, @{x13} <= @{x8} ) {\\n new x14, x15 in {\\n @{(x12, \"getBalance\")}!(x14) |\\n for( @{x16} <- @{x14} ) {\\n @{(x12, \"split\")}!(x16, x15) |\\n for( @{x17} <- @{x15} ) {\\n match x17 {\\n [] => @{x13}!((\"Left\", \"Could not extract funds from given purse\")) ;\\n [x18] => @{x13}!((\"Right\", (x18, x16)))\\n }\\n }\\n }\\n }\\n }\\n }\\n} |\\nfor( @{x0}, @{x1}, @{x2}, @{x3} <= @{\"ed25519Verify\"} ) {\\n Nil\\n} |\\nfor( @{x0}, @{x1} <= @{\"keccak256Hash\"} ) {\\n Nil\\n}',\n", " 'timestamp': 1541548724337,\n", " 'faultTolerance': -1.0,\n", " 'mainParentHash': '8e90e1071b1df8cb84ec0ab06847d5eb6b7e3f708a75b8e1301f3524b317abc7',\n", " 'parentsHashList': ['8e90e1071b1df8cb84ec0ab06847d5eb6b7e3f708a75b8e1301f3524b317abc7'],\n", " 'sender': 'eabe5a1a0750d2a8745709bb0bdb24f63c6a8ac3a887b9bed40b34b0598ddf08',\n", " 'shardId': 'rchain'}" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "block = casper.get_block(connection, block_hash=block_hash)\n", "block" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "block.get('blockNumber')" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Context Manager" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "The connection provided by the library can be used in a `with` python statement" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'success': True, 'message': 'Success! Block bee1f076d5... created and added.'}\n", "Current block number is 2\n", "with hash bee1f076d58eb681743e3ab6376292075a9faf1abf4899fee68d799da6a1ec34\n" ] } ], "source": [ "# all previous operations in one context\n", "\n", "with casper.create_connection(host=RNODE_HOST) as connection:\n", "\n", " # deploy / propose\n", " casper.deploy(connection, rholang_code)\n", " print(casper.propose(connection))\n", " \n", " # handle output\n", " output = casper.get_blocks(connection, depth=1)\n", " block_hash = output.pop().get('blockHash')\n", " block = casper.get_block(connection, block_hash=block_hash)\n", " print(f\"Current block number is {block.get('blockNumber')}\\nwith hash {block_hash}\")\n", " \n", "# connection here is closed" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Interact with channels" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Now we'll take advantage of the `listenForDataAtName` functionality inside the RChain gRPC definition.\n", "\n", "We can specify a channel to receive the results of the new block proposed." ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "output_placeholder = \"your_channel_name\"" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "rholang_code = f\"\"\"\n", "{output_placeholder}!(\"bar\")\n", "\"\"\" " ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "your_channel_name!(\"bar\")\n", "\n" ] } ], "source": [ "print(rholang_code)\n", "\n", "# your_channel_name will be replaced with @\"RANDOMNAME\"" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "with casper.create_connection(host=RNODE_HOST) as connection:\n", " block = casper.run_and_get_value_from(\n", " connection=connection,\n", " term=rholang_code, \n", " # this name gets replaced with a channel name\n", " output_placeholder=output_placeholder\n", " )" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/plain": [ "'ack_ff026dd2fd8a89fc12604abdbe5f4e0552a33c98a3d763b0ef10a975b724'" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# what's used for replacing the placeholder\n", "import secrets\n", "ack_name = f'ack_{secrets.token_hex(30)}'\n", "ack_name" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/plain": [ "{'status': 'Success',\n", " 'blockResults': [{'postBlockData': [['bar']],\n", " 'block': {'blockHash': 'ceaeb77444283f5f19341b39d6e3527c516f80ae19b906940a4f60aa66569966',\n", " 'blockSize': '1146',\n", " 'blockNumber': 3,\n", " 'version': 1,\n", " 'deployCount': 1,\n", " 'tupleSpaceHash': '7bf4c2b8d44b1b25debf422b49ddb8d7a75506227d486709a522d9343576bfef',\n", " 'timestamp': 1541548733670,\n", " 'faultTolerance': -1.0,\n", " 'mainParentHash': 'bee1f076d58eb681743e3ab6376292075a9faf1abf4899fee68d799da6a1ec34',\n", " 'parentsHashList': ['bee1f076d58eb681743e3ab6376292075a9faf1abf4899fee68d799da6a1ec34'],\n", " 'sender': 'eabe5a1a0750d2a8745709bb0bdb24f63c6a8ac3a887b9bed40b34b0598ddf08'}}],\n", " 'length': 1}" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "block" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Received: bar\n" ] } ], "source": [ "results = block.get('blockResults').pop()\n", "\n", "for message in results.get('postBlockData'):\n", " print(\"Received: \", message.pop())" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Name registry\n", "\n", "`NEW!`\n", "\n", "(see [link to specs](https://rchain.atlassian.net/wiki/spaces/RHOL/pages/511541342/Name+registry+specification))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Using the techniques tested so far we can now:\n", "\n", "- write a contract with `unforgeable name`\n", "- register its name to Name Registry (introduced in 0.7) \n", "- and get the id for lookup\n", "\n", "so - all programmatically from Python - \n", "\n", "we can (almost) call a contract in a secure way." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### 1. Register a contract" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "ack_name = 'placeholder_something'" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "rholang_code = \"\"\"\n", "new newName, ack, register(`rho:registry:insertArbitrary`), stdout(`rho:io:stdout`) in\n", "{\n", " register!(bundle+{*newName}, *ack)\n", " |\n", " contract newName(@msg) = {\n", " stdout!(\"Contract called with message: \" ++ msg)\n", " }\n", " |\n", " for (@msg <- ack) {\n", " %s!([\"From registry: \", msg])\n", " }\n", "}\n", "\"\"\" % ack_name" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "new newName, ack, register(`rho:registry:insertArbitrary`), stdout(`rho:io:stdout`) in\n", "{\n", " register!(bundle+{*newName}, *ack)\n", " |\n", " contract newName(@msg) = {\n", " stdout!(\"Contract called with message: \" ++ msg)\n", " }\n", " |\n", " for (@msg <- ack) {\n", " placeholder_something!([\"From registry: \", msg])\n", " }\n", "}\n", "\n" ] } ], "source": [ "print(rholang_code)" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'blockResults': [{'block': {'blockHash': '2b87d1204918bb68e92614fcfea344a2b78b9f1957b6b3c7fea3f0ec8cac6850',\n", " 'blockNumber': 4,\n", " 'blockSize': '3187',\n", " 'deployCount': 1,\n", " 'faultTolerance': -1.0,\n", " 'mainParentHash': 'ceaeb77444283f5f19341b39d6e3527c516f80ae19b906940a4f60aa66569966',\n", " 'parentsHashList': ['ceaeb77444283f5f19341b39d6e3527c516f80ae19b906940a4f60aa66569966'],\n", " 'sender': 'eabe5a1a0750d2a8745709bb0bdb24f63c6a8ac3a887b9bed40b34b0598ddf08',\n", " 'timestamp': 1541548738908,\n", " 'tupleSpaceHash': '109aca205eea7930e9d8a4e9cde311ebeaeb73558c3b43d2083a559c5410ca2f',\n", " 'version': 1},\n", " 'postBlockData': [[{'ps': [['From registry: '],\n", " ['rho:id:rqjd73cs7tuadhamaow7nans57mfpdz96b67gd6ma6ow95eh8zc6ej']]}]]}],\n", " 'length': 1,\n", " 'status': 'Success'}\n" ] } ], "source": [ "# run and get the value in the block output\n", "with casper.create_connection(host=RNODE_HOST) as connection:\n", " block = casper.run_and_get_value_from(connection, rholang_code, ack_name)\n", " \n", "from pprint import pprint\n", "pprint(block)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### 2. WIP: get ID inside the code" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "We are looking to find a better way to handle the \"post block data\" " ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [], "source": [ "post_block_data = block.get('blockResults').pop().get('postBlockData')" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[[{'ps': [['From registry: '],\n", " ['rho:id:rqjd73cs7tuadhamaow7nans57mfpdz96b67gd6ma6ow95eh8zc6ej']]}]]" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "post_block_data" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'rho:id:rqjd73cs7tuadhamaow7nans57mfpdz96b67gd6ma6ow95eh8zc6ej'" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(post_block_data[0][0].values())[0][1][0]" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "# alternative with json/regular expression\n", "\n", "import re\n", "import json\n", "\n", "post_block_str = json.dumps(post_block_data)\n", "\n", "match = re.search(r\"rho:id:[^\\\"]+\", post_block_str)\n", "registry_id = match.group()" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'rho:id:rqjd73cs7tuadhamaow7nans57mfpdz96b67gd6ma6ow95eh8zc6ej'" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "registry_id" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### 3. Lookup and call the contract" ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "new return, lookup(`rho:registry:lookup`), stdout(`rho:io:stdout`) in\n", "{\n", " lookup!(`rho:id:rqjd73cs7tuadhamaow7nans57mfpdz96b67gd6ma6ow95eh8zc6ej`, *return) |\n", " for (myContract <- return) {\n", " myContract!(\"Proof test\")\n", " }\n", "}\n", "\n" ] } ], "source": [ "rholang_code = \"\"\"\n", "new return, lookup(`rho:registry:lookup`), stdout(`rho:io:stdout`) in\n", "{\n", " lookup!(`%s`, *return) |\n", " for (myContract <- return) {\n", " myContract!(\"Proof test\")\n", " }\n", "}\n", "\"\"\" % registry_id\n", "print(rholang_code)" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'success': True, 'message': 'Success!'}\n", "{'success': True, 'message': 'Success! Block fabb9c8e19... created and added.'}\n" ] } ], "source": [ "with casper.create_connection(host=RNODE_HOST) as connection:\n", " print(casper.deploy(connection, rholang_code))\n", " print(casper.propose(connection))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "go check the logs!" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# THE END" ] } ], "metadata": { "celltoolbar": "Slideshow", "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.1" }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": false, "sideBar": true, "skip_h1_title": true, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": { "height": "calc(100% - 180px)", "left": "10px", "top": "150px", "width": "239px" }, "toc_section_display": true, "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 2 }