From 2c66ef3a0d30cd79a10d3d6fa866b58a4e52d723 Mon Sep 17 00:00:00 2001 From: Reuven Podmazo Date: Wed, 3 Feb 2021 16:29:55 +0200 Subject: [PATCH] added support for plaintext logs --- Makefile | 4 +- .../contracts/plaintext-logs/.cargo/config | 6 + cosmwasm/contracts/plaintext-logs/.gitignore | 1 + cosmwasm/contracts/plaintext-logs/Cargo.lock | 251 ++++++++++++++++++ cosmwasm/contracts/plaintext-logs/Cargo.toml | 38 +++ cosmwasm/contracts/plaintext-logs/Makefile | 16 ++ .../contracts/plaintext-logs/src/contract.rs | 38 +++ cosmwasm/contracts/plaintext-logs/src/lib.rs | 5 + cosmwasm/contracts/plaintext-logs/src/msg.rs | 14 + cosmwasm/packages/std/src/init_handle.rs | 17 ++ cosmwasm/packages/std/src/lib.rs | 5 +- .../wasmi-runtime/src/cosmwasm/types.rs | 28 +- .../packages/wasmi-runtime/src/wasm/io.rs | 2 +- x/compute/client/cli/query.go | 26 +- 14 files changed, 430 insertions(+), 21 deletions(-) create mode 100644 cosmwasm/contracts/plaintext-logs/.cargo/config create mode 100644 cosmwasm/contracts/plaintext-logs/.gitignore create mode 100644 cosmwasm/contracts/plaintext-logs/Cargo.lock create mode 100644 cosmwasm/contracts/plaintext-logs/Cargo.toml create mode 100644 cosmwasm/contracts/plaintext-logs/Makefile create mode 100644 cosmwasm/contracts/plaintext-logs/src/contract.rs create mode 100644 cosmwasm/contracts/plaintext-logs/src/lib.rs create mode 100644 cosmwasm/contracts/plaintext-logs/src/msg.rs diff --git a/Makefile b/Makefile index bac2eab23..abdf3f38c 100644 --- a/Makefile +++ b/Makefile @@ -211,7 +211,7 @@ clean: $(MAKE) -C go-cosmwasm clean-all $(MAKE) -C cosmwasm/packages/wasmi-runtime clean -build-dev-image: docker_base +build-dev-image: docker build --build-arg BUILD_VERSION=${VERSION} --build-arg SGX_MODE=SW --build-arg FEATURES= -f deployment/dockerfiles/base.Dockerfile -t rust-go-base-image . docker build --build-arg SGX_MODE=SW --build-arg SECRET_NODE_TYPE=BOOTSTRAP -f deployment/dockerfiles/release.Dockerfile -t enigmampc/secret-network-sw-dev:${DOCKER_TAG} . @@ -357,7 +357,7 @@ secretjs-build: # Before running this, first make sure: # 1. To `npm login` with enigma-dev -# 2. The new version is updated in `cosmwasm-js/packages/sdk/package.json` +# 2. The new version is updated in `cosmwasm-js/packages/sdk/package.json` secretjs-publish-npm: secretjs-build cd cosmwasm-js/packages/sdk && npm publish diff --git a/cosmwasm/contracts/plaintext-logs/.cargo/config b/cosmwasm/contracts/plaintext-logs/.cargo/config new file mode 100644 index 000000000..7c115322a --- /dev/null +++ b/cosmwasm/contracts/plaintext-logs/.cargo/config @@ -0,0 +1,6 @@ +[alias] +wasm = "build --release --target wasm32-unknown-unknown" +wasm-debug = "build --target wasm32-unknown-unknown" +unit-test = "test --lib --features backtraces" +integration-test = "test --test integration" +schema = "run --example schema" diff --git a/cosmwasm/contracts/plaintext-logs/.gitignore b/cosmwasm/contracts/plaintext-logs/.gitignore new file mode 100644 index 000000000..ea3e9a6ad --- /dev/null +++ b/cosmwasm/contracts/plaintext-logs/.gitignore @@ -0,0 +1 @@ +contract.wasm.gz diff --git a/cosmwasm/contracts/plaintext-logs/Cargo.lock b/cosmwasm/contracts/plaintext-logs/Cargo.lock new file mode 100644 index 000000000..ebeea9eb6 --- /dev/null +++ b/cosmwasm/contracts/plaintext-logs/Cargo.lock @@ -0,0 +1,251 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "addr2line" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55f82cfe485775d02112886f4169bde0c5894d75e79ead7eafe7e40a25e45f7" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "backtrace" +version = "0.3.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d117600f438b1707d4e4ae15d3595657288f8235a0eb593e80ecc98ab34e1bc" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cosmwasm-std" +version = "0.10.0" +dependencies = [ + "base64", + "schemars", + "serde", + "serde-json-wasm", + "snafu", +] + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "gimli" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" + +[[package]] +name = "itoa" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" + +[[package]] +name = "libc" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cca32fa0182e8c0989459524dc356b8f2b5c10f1b9eb521b7d182c03cf8c5ff" + +[[package]] +name = "miniz_oxide" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d" +dependencies = [ + "adler", + "autocfg", +] + +[[package]] +name = "object" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4" + +[[package]] +name = "plaintext-logs" +version = "0.1.0" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", +] + +[[package]] +name = "proc-macro2" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232" + +[[package]] +name = "ryu" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" + +[[package]] +name = "schemars" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be77ed66abed6954aabf6a3e31a84706bedbf93750d267e92ef4a6d90bbd6a61" +dependencies = [ + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11af7a475c9ee266cfaa9e303a47c830ebe072bf3101ab907a7b7b9d816fa01d" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn", +] + +[[package]] +name = "serde" +version = "1.0.123" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-json-wasm" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120bad73306616e91acd7ceed522ba96032a51cffeef3cc813de7f367df71e37" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.123" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_derive_internals" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dbab34ca63057a1f15280bdf3c39f2b1eb1b54c17e98360e511637aef7418c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "snafu" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eab12d3c261b2308b0d80c26fffb58d17eba81a4be97890101f416b478c79ca7" +dependencies = [ + "backtrace", + "doc-comment", + "snafu-derive", +] + +[[package]] +name = "snafu-derive" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1508efa03c362e23817f96cde18abed596a25219a8b2c66e8db33c03543d315b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "1.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "unicode-xid" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" diff --git a/cosmwasm/contracts/plaintext-logs/Cargo.toml b/cosmwasm/contracts/plaintext-logs/Cargo.toml new file mode 100644 index 000000000..56bd9f90e --- /dev/null +++ b/cosmwasm/contracts/plaintext-logs/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "plaintext-logs" +version = "0.1.0" +edition = "2018" + +exclude = [ + # Those files are rust-optimizer artifacts. You might want to commit them for convenience but they should not be part of the source code publication. + "contract.wasm", + "hash.txt", +] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[profile.release] +opt-level = 3 +debug = false +rpath = false +lto = true +debug-assertions = false +codegen-units = 1 +panic = 'abort' +incremental = false +overflow-checks = true + +[features] +default = [] +# for quicker tests, cargo test --lib +# for more explicit tests, cargo test --features=backtraces +backtraces = ["cosmwasm-std/backtraces"] + +[dependencies] +cosmwasm-std = { path = "../../packages/std", features = ["iterator"] } +schemars = "0.7" +serde = { version = "1.0.103", default-features = false, features = ["derive"] } +#snafu = { version = "0.6.3" } diff --git a/cosmwasm/contracts/plaintext-logs/Makefile b/cosmwasm/contracts/plaintext-logs/Makefile new file mode 100644 index 000000000..c08647e00 --- /dev/null +++ b/cosmwasm/contracts/plaintext-logs/Makefile @@ -0,0 +1,16 @@ +.PHONY: start-server +start-server: # CTRL+C to stop + docker run -it --rm \ + -p 26657:26657 -p 26656:26656 -p 1317:1317 \ + -v $$(pwd):/root/code \ + --name secretdev enigmampc/secret-network-sw-dev:latest + +.PHONY: compile-optimized _compile-optimized +compile-optimized: _compile-optimized contract.wasm.gz +_compile-optimized: + RUSTFLAGS='-C link-arg=-s' cargo build --release --target wasm32-unknown-unknown --locked + @# The following line is not necessary, may work only on linux (extra size optimization) + wasm-opt -Os ./target/wasm32-unknown-unknown/release/*.wasm -o ./contract.wasm + +contract.wasm.gz: contract.wasm + cat ./contract.wasm | gzip -9 > ./contract.wasm.gz diff --git a/cosmwasm/contracts/plaintext-logs/src/contract.rs b/cosmwasm/contracts/plaintext-logs/src/contract.rs new file mode 100644 index 000000000..514dd4f90 --- /dev/null +++ b/cosmwasm/contracts/plaintext-logs/src/contract.rs @@ -0,0 +1,38 @@ +use cosmwasm_std::{ + log, plaintext_log, Api, Binary, Env, Extern, HandleResponse, InitResponse, Querier, StdError, + StdResult, Storage, +}; + +use crate::msg::{HandleMsg, InitMsg, QueryMsg}; + +pub fn init( + _deps: &mut Extern, + _env: Env, + _msg: InitMsg, +) -> StdResult { + Ok(InitResponse::default()) +} + +pub fn handle( + _deps: &mut Extern, + _env: Env, + _msg: HandleMsg, +) -> StdResult { + let response = HandleResponse { + messages: vec![], + data: None, + log: vec![ + log("encrypted log", "encrypted value"), + log("ZW5jb2RlZCBsb2cK", "ZW5jb2RlZCB2YWx1ZQo="), // base64 + plaintext_log("plaintext log", "plaintext value"), + ], + }; + Ok(response) +} + +pub fn query( + _deps: &Extern, + _msg: QueryMsg, +) -> StdResult { + Err(StdError::generic_err("")) +} diff --git a/cosmwasm/contracts/plaintext-logs/src/lib.rs b/cosmwasm/contracts/plaintext-logs/src/lib.rs new file mode 100644 index 000000000..128111a48 --- /dev/null +++ b/cosmwasm/contracts/plaintext-logs/src/lib.rs @@ -0,0 +1,5 @@ +pub mod contract; +pub mod msg; + +#[cfg(target_arch = "wasm32")] +cosmwasm_std::create_entry_points!(contract); diff --git a/cosmwasm/contracts/plaintext-logs/src/msg.rs b/cosmwasm/contracts/plaintext-logs/src/msg.rs new file mode 100644 index 000000000..45d12701f --- /dev/null +++ b/cosmwasm/contracts/plaintext-logs/src/msg.rs @@ -0,0 +1,14 @@ +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +/// InitMsg is a placeholder where we don't take any input +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct InitMsg {} + +/// HandleMsg is a placeholder where we don't take any input +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct HandleMsg {} + +/// QueryMsg is a placeholder where we don't take any input +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct QueryMsg {} diff --git a/cosmwasm/packages/std/src/init_handle.rs b/cosmwasm/packages/std/src/init_handle.rs index f823cecd8..5254fcf5b 100644 --- a/cosmwasm/packages/std/src/init_handle.rs +++ b/cosmwasm/packages/std/src/init_handle.rs @@ -141,6 +141,7 @@ impl From for CosmosMsg pub struct LogAttribute { pub key: String, pub value: String, + pub encrypted: bool, } /// A shorthand to produce a log attribute @@ -148,6 +149,16 @@ pub fn log(key: K, value: V) -> LogAttribute { LogAttribute { key: key.to_string(), value: value.to_string(), + encrypted: true, + } +} + +/// A shorthand to produce a plaintext log attribute +pub fn plaintext_log(key: K, value: V) -> LogAttribute { + LogAttribute { + key: key.to_string(), + value: value.to_string(), + encrypted: false, } } @@ -305,6 +316,10 @@ where self.log.push(log(key, value)); } + pub fn add_plaintext_log(&mut self, key: K, value: V) { + self.log.push(plaintext_log(key, value)); + } + pub fn add_message>>(&mut self, msg: U) { self.messages.push(msg.into()); } @@ -326,6 +341,7 @@ mod test { let expeceted = LogAttribute { key: "foo".to_string(), value: "42".to_string(), + encrypted: true, }; assert_eq!(log("foo", "42"), expeceted); @@ -357,6 +373,7 @@ mod test { log: vec![LogAttribute { key: "action".to_string(), value: "release".to_string(), + encrypted: true, }], }); let bin = to_vec(&send).expect("encode contract result"); diff --git a/cosmwasm/packages/std/src/lib.rs b/cosmwasm/packages/std/src/lib.rs index a2367a46e..88d3c0d4c 100644 --- a/cosmwasm/packages/std/src/lib.rs +++ b/cosmwasm/packages/std/src/lib.rs @@ -20,8 +20,9 @@ pub use crate::coins::{coin, coins, has_coins, Coin}; pub use crate::encoding::Binary; pub use crate::errors::{StdError, StdResult, SystemError, SystemResult}; pub use crate::init_handle::{ - log, BankMsg, Context, CosmosMsg, GovMsg, HandleResponse, HandleResult, InitResponse, - InitResult, LogAttribute, MigrateResponse, MigrateResult, StakingMsg, VoteOption, WasmMsg, + log, plaintext_log, BankMsg, Context, CosmosMsg, GovMsg, HandleResponse, HandleResult, + InitResponse, InitResult, LogAttribute, MigrateResponse, MigrateResult, StakingMsg, VoteOption, + WasmMsg, }; #[cfg(feature = "iterator")] pub use crate::iterator::{Order, KV}; diff --git a/cosmwasm/packages/wasmi-runtime/src/cosmwasm/types.rs b/cosmwasm/packages/wasmi-runtime/src/cosmwasm/types.rs index dcad89a28..067880a4f 100644 --- a/cosmwasm/packages/wasmi-runtime/src/cosmwasm/types.rs +++ b/cosmwasm/packages/wasmi-runtime/src/cosmwasm/types.rs @@ -302,10 +302,24 @@ impl From for CosmosMsg { } } +/// Return true +/// +/// Only used for serde annotations +fn bool_true() -> bool { + true +} + #[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq)] pub struct LogAttribute { pub key: String, pub value: String, + /// nonstandard late addition, thus optional and only used in deserialization. + /// The contracts may return this in newer versions that support distinguishing + /// encrypted and plaintext logs. We naturally default to encrypted logs, and + /// don't serialize the field later so it doesn't leak up to the Go layers. + #[serde(default = "bool_true")] + #[serde(skip_serializing)] + pub encrypted: bool, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] @@ -337,11 +351,21 @@ pub fn coin(amount: &str, denom: &str) -> Vec { }] } -// log is shorthand to produce log messages -pub fn log(key: &str, value: &str) -> LogAttribute { +/// A shorthand to produce a log attribute +pub fn log(key: K, value: V) -> LogAttribute { + LogAttribute { + key: key.to_string(), + value: value.to_string(), + encrypted: true, + } +} + +/// A shorthand to produce a plaintext log attribute +pub fn plaintext_log(key: K, value: V) -> LogAttribute { LogAttribute { key: key.to_string(), value: value.to_string(), + encrypted: false, } } diff --git a/cosmwasm/packages/wasmi-runtime/src/wasm/io.rs b/cosmwasm/packages/wasmi-runtime/src/wasm/io.rs index cf09ac901..01f8fbb04 100644 --- a/cosmwasm/packages/wasmi-runtime/src/wasm/io.rs +++ b/cosmwasm/packages/wasmi-runtime/src/wasm/io.rs @@ -105,7 +105,7 @@ pub fn encrypt_output( } } - for log in &mut ok.log { + for log in ok.log.iter_mut().filter(|log| log.encrypted) { log.key = encrypt_preserialized_string(&key, &log.key)?; log.value = encrypt_preserialized_string(&key, &log.value)?; } diff --git a/x/compute/client/cli/query.go b/x/compute/client/cli/query.go index 9bfa1ddf6..fa049659c 100644 --- a/x/compute/client/cli/query.go +++ b/x/compute/client/cli/query.go @@ -381,28 +381,26 @@ func GetQueryDecryptTxCmd(cdc *amino.Codec) *cobra.Command { if a.Key != "contract_address" { // key if a.Key != "" { + // Try to decrypt the log key. If it doesn't look encrypted, leave it as-is keyCiphertext, err := base64.StdEncoding.DecodeString(a.Key) - if err != nil { - return fmt.Errorf("error while trying to decode the log key '%s' from base64: %w", a.Key, err) + if err == nil { + keyPlaintext, err := wasmCtx.Decrypt(keyCiphertext, nonce) + if err == nil { + a.Key = string(keyPlaintext) + } } - keyPlaintext, err := wasmCtx.Decrypt(keyCiphertext, nonce) - if err != nil { - return fmt.Errorf("error while trying to decrypt the log key '%s' from base64: %w", a.Key, err) - } - a.Key = string(keyPlaintext) } // value if a.Value != "" { + // Try to decrypt the log value. If it doesn't look encrypted, leave it as-is valueCiphertext, err := base64.StdEncoding.DecodeString(a.Value) - if err != nil { - return fmt.Errorf("error while trying to decode the log value '%s' from base64: %w", a.Value, err) - } - valuePlaintext, err := wasmCtx.Decrypt(valueCiphertext, nonce) - if err != nil { - return fmt.Errorf("error while trying to decrypt the log value '%s' from base64: %w", a.Value, err) + if err == nil { + valuePlaintext, err := wasmCtx.Decrypt(valueCiphertext, nonce) + if err == nil { + a.Value = string(valuePlaintext) + } } - a.Value = string(valuePlaintext) } e.Attributes[i] = a