diff --git a/contrib/mir/.gitignore b/contrib/mir/.gitignore index de783a39f8f25c4be8a50ddc0ba4cb088ae24279..b6a4c5a8eab4c2fdc28403e146dd3ecce5ca626c 100644 --- a/contrib/mir/.gitignore +++ b/contrib/mir/.gitignore @@ -1 +1,3 @@ src/syntax.rs +bin/ +.tezos-smart-rollup-node/ diff --git a/contrib/mir/Cargo.lock b/contrib/mir/Cargo.lock index 10321e67916e55526a49d7c1ead748395002529b..cb016799f8a1fffbd67b0d21ba8df6ead330e9ae 100644 --- a/contrib/mir/Cargo.lock +++ b/contrib/mir/Cargo.lock @@ -371,12 +371,6 @@ dependencies = [ "libc", ] -[[package]] -name = "fastrand" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" - [[package]] name = "ff" version = "0.10.1" @@ -399,12 +393,6 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - [[package]] name = "funty" version = "2.0.0" @@ -421,17 +409,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - [[package]] name = "getrandom" version = "0.2.10" @@ -440,7 +417,7 @@ checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", ] [[package]] @@ -586,12 +563,6 @@ version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" -[[package]] -name = "libm" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" - [[package]] name = "libsecp256k1" version = "0.7.1" @@ -606,7 +577,6 @@ dependencies = [ "libsecp256k1-gen-genmult", "rand 0.8.5", "serde", - "sha2 0.9.9", ] [[package]] @@ -711,7 +681,6 @@ dependencies = [ "autocfg", "num-integer", "num-traits", - "rand 0.7.3", "serde", ] @@ -732,7 +701,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", - "libm", ] [[package]] @@ -868,32 +836,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "proptest" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e35c06b98bf36aba164cc17cb25f7e232f5c4aeea73baa14b8a9f0d92dbfa65" -dependencies = [ - "bit-set", - "bitflags 1.3.2", - "byteorder", - "lazy_static", - "num-traits", - "rand 0.8.5", - "rand_chacha 0.3.1", - "rand_xorshift", - "regex-syntax 0.6.29", - "rusty-fork", - "tempfile", - "unarray", -] - -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - [[package]] name = "quote" version = "1.0.33" @@ -915,9 +857,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", + "rand_chacha", "rand_core 0.5.1", "rand_hc", ] @@ -928,8 +868,6 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "libc", - "rand_chacha 0.3.1", "rand_core 0.6.4", ] @@ -943,33 +881,17 @@ dependencies = [ "rand_core 0.5.1", ] -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", -] - [[package]] name = "rand_core" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] [[package]] name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.10", -] [[package]] name = "rand_hc" @@ -980,15 +902,6 @@ dependencies = [ "rand_core 0.5.1", ] -[[package]] -name = "rand_xorshift" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" -dependencies = [ - "rand_core 0.6.4", -] - [[package]] name = "redox_syscall" version = "0.2.16" @@ -1013,7 +926,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom 0.2.10", + "getrandom", "redox_syscall 0.2.16", "thiserror", ] @@ -1081,18 +994,6 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" -[[package]] -name = "rusty-fork" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" -dependencies = [ - "fnv", - "quick-error", - "tempfile", - "wait-timeout", -] - [[package]] name = "scopeguard" version = "1.2.0" @@ -1242,19 +1143,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" -[[package]] -name = "tempfile" -version = "3.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" -dependencies = [ - "cfg-if", - "fastrand", - "redox_syscall 0.3.5", - "rustix", - "windows-sys", -] - [[package]] name = "term" version = "0.7.0" @@ -1395,7 +1283,6 @@ dependencies = [ "num-bigint", "num-traits", "p256", - "proptest", "rand 0.7.3", "serde", "strum", @@ -1508,12 +1395,6 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" -[[package]] -name = "unarray" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" - [[package]] name = "unicode-ident" version = "1.0.12" @@ -1538,21 +1419,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "wait-timeout" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" -dependencies = [ - "libc", -] - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/contrib/mir/Cargo.toml b/contrib/mir/Cargo.toml index 612ae85ee3b6fd153a4de3d2048d5438333f6c3a..2a780dbd9c6c32781b75aa2dfaccf4bce5779f7a 100644 --- a/contrib/mir/Cargo.toml +++ b/contrib/mir/Cargo.toml @@ -16,8 +16,8 @@ lalrpop = "0.20.0" [dependencies] lalrpop-util = { version = "0.20.0", features = ["lexer"] } num-bigint = "0.3.3" +tezos_crypto_rs = { version = "0.5.1", default-features = false } tezos_data_encoding = "0.5.1" -tezos_crypto_rs = "0.5.1" tezos-smart-rollup = "0.2.1" tezos-smart-rollup-encoding = "0.2.1" tezos-smart-rollup-mock = "0.2.1" diff --git a/contrib/mir/Makefile b/contrib/mir/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..8635983930230b90c09cef2f72e37fcc7cabe151 --- /dev/null +++ b/contrib/mir/Makefile @@ -0,0 +1,96 @@ +# SPDX-FileCopyrightText: 2023 Serokell +# SPDX-FileCopyrightText: 2023 Baking Bad +# +# SPDX-License-Identifier: MIT + +.PHONY: build fill-kernel-chunks prepare-smart-rollup-config originate_rollup clean-rollup-dir clean-build clean + +# Folders +BIN_DIR ?= bin +TARGET_DIR ?= target +# Where temporary folder of rollup node will be +SMART_ROLLUP_NODE_DIR ?= .tezos-smart-rollup-node + +# Executables +SMART_ROLLUP_INSTALLER ?= smart-rollup-installer + +# Addresses +## Alias for the originated rollup +ROLLUP_ALIAS ?= mir-rollup +## Address that will pay for operations +OPERATOR_ADDR ?= rollup-operator + +# Produces the immediate .wasm kernel created by Rust +$(BIN_DIR)/mir-raw-kernel.wasm: $(shell find src) Cargo.toml + mkdir -p $(BIN_DIR) + cargo build --release --target wasm32-unknown-unknown + cp $(TARGET_DIR)/wasm32-unknown-unknown/release/mir.wasm $(BIN_DIR)/mir-raw-kernel.wasm + +# Applies the processing to the kernel that is suggested by all tutorials +$(BIN_DIR)/mir-kernel.wasm: $(BIN_DIR)/mir-raw-kernel.wasm + wasm-strip $(BIN_DIR)/mir-raw-kernel.wasm -o $(BIN_DIR)/mir-kernel.wasm + +# No real kernel would fit into Tezos' operation size limits, so we have +# to use a dedicated tool that would split the kernel into chunks and create +# an installer kernel that would load those chunks on run. +# The chunks have to be exposed via our local rollup node. +$(BIN_DIR)/mir-installer-kernel.wasm: $(BIN_DIR)/mir-kernel.wasm + ifeq ($(SMART_ROLLUP_INSTALLER),smart-rollup-installer) + ifeq (, $(shell which smart-rollup-installer)) + $(error "No smart-rollup-installer in $$PATH, you can install it with `cargo install`. \ + Make sure cargo binaries folder is in your path") + endif + endif + $(SMART_ROLLUP_INSTALLER) get-reveal-installer \ + --upgrade-to $(BIN_DIR)/mir-kernel.wasm \ + --output $(BIN_DIR)/mir-installer-kernel.wasm \ + --preimages-dir $(BIN_DIR)/wasm_2_0_0 + +%-kernel.wasm.hex: %-kernel.wasm + xxd -ps -c 0 $*-kernel.wasm | tr -d '\n' > $@ + +build: $(BIN_DIR)/mir-installer-kernel.wasm.hex + +# Load the kernel chunks into the local node's dir +fill-kernel-chunks: $(BIN_DIR)/mir-installer-kernel.wasm.hex + mkdir -p $(SMART_ROLLUP_NODE_DIR)/wasm_2_0_0 + cp -r $(BIN_DIR)/wasm_2_0_0 $(SMART_ROLLUP_NODE_DIR)/ + +originate-rollup: $(BIN_DIR)/mir-installer-kernel.wasm.hex + octez-client originate smart rollup $(ROLLUP_ALIAS) \ + from $(OPERATOR_ADDR) \ + of kind wasm_2_0_0 \ + of type int \ + with kernel $(BIN_DIR)/mir-installer-kernel.wasm.hex \ + --burn-cap 999 --fee-cap 100 \ + --force + +# Run this in background in order for rollup operations to take progress. +# +# We'll bind the node to be an operator of the originated rollup, and that won't +# work without removing the previous operators from the config. +run-rollup-node: clean-rollup-dir fill-kernel-chunks + + octez-smart-rollup-node init operator config \ + for "$(ROLLUP_ALIAS)" \ + with operators "$(OPERATOR_ADDR)" \ + --data-dir "$(SMART_ROLLUP_NODE_DIR)" \ + --force + + octez-smart-rollup-node \ + run operator for "$(ROLLUP_ALIAS)" \ + with operators "$(OPERATOR_ADDR)" \ + --data-dir "$(SMART_ROLLUP_NODE_DIR)" + +clean-rollup-dir: + @# Trying to remove safely + $(if $(SMART_ROLLUP_NODE_DIR),,$(error SMART_ROLLUP_NODE_DIR var is empty)) + rm -rf $(SMART_ROLLUP_NODE_DIR) + +clean-build: + @# Trying to remove safely + $(if $(BIN_DIR),,$(error BIN_DIR var is empty)) + rm -rf $(BIN_DIR) + rm -rf ./target + +clean: clean-build clean-rollup-dir diff --git a/contrib/mir/docs/testing-with-deployment.md b/contrib/mir/docs/testing-with-deployment.md new file mode 100644 index 0000000000000000000000000000000000000000..8a72a2ec76bace4d2cf3d79901c70c15957f5832 --- /dev/null +++ b/contrib/mir/docs/testing-with-deployment.md @@ -0,0 +1,175 @@ + + +## Prerequisites + +You will need the following programs installed: + +* Rust with rustup: [install page](https://www.rust-lang.org/tools/install). +* `xxd` command line tool. +* `wasm-strip`: it's simplest to install from releases of + [`wabt`](https://github.com/WebAssembly/wabt/) repository. +* Some `octez-*` tools: build them from sources or use static + binaries that can be found in releases of [`tezos + packaging`](https://github.com/serokell/tezos-packaging) repository. + * `octez-client`; + * `octez-smart-rollup-client`; + * `octez-smart-rollup-node`. +* `tezos-smart-rollup-installer`: use `cargo install tezos-smart-rollup-installer`. + +Make sure that your data directory of `octez-client` (`~/.octez-client` by default) +mentions the testing network you are planning to operate with. + +Also, you will need an address with some tez on it, provide it via the dedicated +variable: + +```sh +export OPERATOR_ADDR="ADDRESS or ALIAS" +``` + +If this variable is not provided, `rollup-operator` alias will be picked. You +may want to just expose this alias instead of providing operator address each +time you test, for that call + +```sh +octez-client gen keys rollup-operator +octez-client transfer 1000 from RICH_ADDRESS to rollup-operator --burn-cap 0.1 +``` + +There are numerious restrictions in case you care about rollup actions being +cemented: the operator must have at least 10,000 tez, and commitment with your +action will be published only in 2 weeks unless you are using a dedicated exotic +testing network like Dailynet. But to test the rollup kernel's behaviour that's +not strictly necessary. + +## Deploy + +Run + +```sh +make originate-rollup +``` + +This will build the kernel and deploy it. + +Once the origination command finishes, the originated rollup will reside under +`mir-rollup` alias, unless you specify `ROLLUP_ALIAS` env variable with the +desired name to the command. + +Further, in order for the rollup execution to take place, you need to run +a local node. This is doable by calling + +```sh +make run-rollup-node +``` + +Let it execute in the background. + +When idle, the running node causes the rollup to process a few service internal +messages at every level. + +## Testing + +### Invoking kernel with an external message + +To send an external message use a command like follows: + +```sh +octez-client send smart rollup message "hex:[\"05\"]" from $OPERATOR_ADDR +``` + +(the specified address should not necessarily be operator address, but we use it for simplicity). + +### Checking result + +Then observe the result written in the durable storage via + +```sh +octez-smart-rollup-client rpc get '/global/block/head/durable/wasm_2_0_0/value?key=/storage' +``` + +The provided request refers to the current optimistic state, not the cemeneted +one, meaning that actions on the rollup should be visible by that call +immediately. `head` can be replaced with `cemented` or specific level, see `man` +on the command for details. + +### Invoking kernel with an internal message + +For sending an internal message, a dedicated contract is necessary through which +we would call our rollup. + +First, obtain the rollup address via + +```sh +octez-smart-rollup-client get smart rollup address +``` + +(the tezos smart rollup node must be running). + +Then follow [the related section of the manual](https://tezos.gitlab.io/shell/smart_rollup_node.html#sending-an-internal-inbox-message) +on how to send the message. + +## Trobleshooting + +In case something is not working, a few investigation directions further. + +### Dead services + +Track the logs of the running node. In case you see that only the `injector` +service is logging something for a long time, then something is off. +If you can find + +``` +Entering degraded mode: only playing refutation game to defend commitments. +``` + +message, then the node will not push the progress forward. + +One of the reasons can be that you rebuilt the kernel, but the rollup node still +serves the old rollup that requires old kernel pages in `wasm_2_0_0` folder that +are not present there anymore. + +### Node accepted the messages + +Once the message to the rollup is included into the chain, in the node you +should be able to see + +``` +....sc_rollup_node.inbox: Fetching 1 messages from block +....sc_rollup_node.inbox: BLXEJoyghMZ6wdbprNEvGc5LjzsY4P7BhVs9myYvLoQE848pNDq at level L +....sc_rollup_node.inbox: Transitioned PVM at inbox level L to +....sc_rollup_node.inbox: srs132pyW4BFZfgRgTL9jWTaqH4VdMu5wMWu8TvkSK8BYXfb8zwJkA at tick 99000000000 +....sc_rollup_node.inbox: with 4 messages +``` + +Here +* `L` is the level of block where the message to our rollup was included. The + rollup kernel will see same level `L` when reading the message from its inbox. +* "Fetching 1 messages" at the first line again refers to your submitted + message. +* "with 4 messages" at the last line refers to your submitted message + 3 + messages added by Tezos protocol. + +### Seeing no "Fetching 1 messages", only 0 + +It might be that `inbox` service falls behind and is still processing the old +blocks, you can compare the block numbers to check whether this is the case. + +If it is, just wait for the `inbox` service to sync up. + +### No `last_seen_block` + +You can see the following error message: + +``` +....sc_rollup_node.injector: [tz1hGdJumKDnZ: publish, add_messages, cement, refute] ignoring unreadable +....sc_rollup_node.injector: file .tezos-smart-rollup-node/injector/last_seen_head on disk: +....sc_rollup_node.injector: Error: +....sc_rollup_node.injector: The persistent element .tezos-smart-rollup-node/injector/last_seen_head could not be read, +... +``` + +It is _fine_ and does not affect operability. diff --git a/contrib/mir/src/rollup/kernel.rs b/contrib/mir/src/rollup/kernel.rs index 07340ad42136d18383001092c8b3eb744287ef65..3e42ddefa4cd7048b031e4971ded76476c57bf3a 100644 --- a/contrib/mir/src/rollup/kernel.rs +++ b/contrib/mir/src/rollup/kernel.rs @@ -8,6 +8,7 @@ use tezos_smart_rollup::{ inbox::{InboxMessage, InternalInboxMessage}, prelude::{debug_msg, Runtime}, + storage::path::RefPath, types::Message, }; @@ -25,7 +26,9 @@ pub type Error = String; /// level to handle some of the messages in the inbox, mind the limits on /// execution time of one such call. pub fn kernel_entry(host: &mut impl Runtime) { + // Ways of observing that kernel has indeed been invoked, helps in testing debug_msg!(host, "Kernel invoked"); + let _ = host.store_write(&RefPath::assert_from(b"/started"), &[1], 0); let mut first_message_for_invocation = true; // Handle all the messages we got at this level diff --git a/contrib/mir/src/rollup/types.rs b/contrib/mir/src/rollup/types.rs index 2916b55129249e10249fad2b2866c86452657a22..dc0fd50b4fd8159ab36e593a145898dfc2d39db9 100644 --- a/contrib/mir/src/rollup/types.rs +++ b/contrib/mir/src/rollup/types.rs @@ -10,6 +10,7 @@ use tezos_smart_rollup::michelson::MichelsonInt; /// What we accept in internal messages as payload (i.e. what is our parameter /// type). /// -/// If you change this, then in the rollup origination command you should also +/// If you change this, then in the rollup origination command +/// `octez-client originate smart rollup ...` you should also /// change the `type` CLI argument respectively. pub type IncomingTransferParam = MichelsonInt;