From b16fa17c4d1d10d075236f8aa1ca1cf6f1501b3a Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Fri, 19 Jun 2026 22:06:47 +0900 Subject: [PATCH 001/124] =?UTF-8?q?feat(executor):=20rework=20runner=20ids?= =?UTF-8?q?=20(contract/chain/custom)=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- configure.rb | 4 + doc/schemas/runners.json | 31 +++- executor/src/rt/supervisor/actions.rs | 251 +++++++++++++++++--------- executor/src/rt/supervisor/mod.rs | 34 +++- executor/src/rt/vm/storage.rs | 7 + executor/src/runners/mod.rs | 122 ++++++++++++- executor/src/runners/ustar.rs | 1 + runners/genlayer-py-std/default.nix | 4 +- runners/support/versions/current.nix | 4 +- 9 files changed, 365 insertions(+), 93 deletions(-) diff --git a/configure.rb b/configure.rb index 5c2c7f558..d2151e5a3 100755 --- a/configure.rb +++ b/configure.rb @@ -483,14 +483,18 @@ def generator.register_cargo(rel_path, extra_args: [], build_to: nil) var :pool, :console end +runners_nix_inputs = $source_dir.join('runners').glob('**/*.nix') + generator.build(:nix_eval, 'out/executor/vTEST/data/latest.json') do var 'expr', 'let drv = import ./runners { host-system = builtins.currentSystem; } ; conv-hash = hash: if hash == "test" then "test" else builtins.convertHash { inherit hash; toHashFormat = "nix32"; } ; in builtins.listToAttrs (builtins.map (x: { name = x.id; value = conv-hash x.hash; }) drv)' var 'wd', $source_dir + add_implicit_dependency runners_nix_inputs end generator.build(:nix_eval, 'out/executor/vTEST/data/all.json') do var 'expr', 'let drv = import ./runners { host-system = builtins.currentSystem; } ; conv-hash = hash: if hash == "test" then "test" else builtins.convertHash { inherit hash; toHashFormat = "nix32"; } ; in builtins.listToAttrs (builtins.map (x: { name = x.id; value = [ (conv-hash x.hash) ]; }) drv)' var 'wd', $source_dir + add_implicit_dependency runners_nix_inputs end generator.build(:phony, 'all/data') do diff --git a/doc/schemas/runners.json b/doc/schemas/runners.json index 86751c0e5..ac3571235 100644 --- a/doc/schemas/runners.json +++ b/doc/schemas/runners.json @@ -11,6 +11,28 @@ "WasmMode": { "enum": ["det", "nondet"] }, + "runner-id": { + "type": "string", + "description": "Identifier of a runner to load", + "anyOf": [ + { + "pattern": "^[a-zA-Z0-9_-]+:[a-zA-Z0-9_=-]+$", + "description": "`name:hash` — packaged runner by human readable name and archive hash (in debug mode hash may be `test`/`latest`)" + }, + { + "const": "contract", + "description": "the runner of the contract that is currently being executed" + }, + { + "pattern": "^chain:0x[0-9a-fA-F]{40}:[af]:0x[0-9a-fA-F]{64}$", + "description": "`chain:
::` — code blob read from a `0x` 20 byte address at a `0x` 32 byte slot, `a`=accepted / `f`=finalized" + }, + { + "pattern": "^custom:[a-zA-Z0-9_=-]+$", + "description": "`custom:` — runner registered at runtime" + } + ] + }, "InitAction": { "description": "A single rule for loading.", "type": "object", @@ -116,8 +138,8 @@ "type": "string" }, "Depends": { - "description": "Depend on other runner by id:hash", - "type": "string" + "description": "Depend on another runner", + "$ref": "#/definitions/runner-id" }, "Seq": { "description": "Execute sequence", @@ -138,7 +160,10 @@ "description": "Makes given runner current without executing it's action. It means that MapFile will fork with files from this archive. Useful for creating lock files", "type": "object", "properties": { - "runner": { "type": "string" }, + "runner": { + "description": "runner id to make current", + "$ref": "#/definitions/runner-id" + }, "action": { "$ref": "#/definitions/InitAction" } } } diff --git a/executor/src/rt/supervisor/actions.rs b/executor/src/rt/supervisor/actions.rs index 612fcad4d..fc33303cf 100644 --- a/executor/src/rt/supervisor/actions.rs +++ b/executor/src/rt/supervisor/actions.rs @@ -28,97 +28,185 @@ fn maps_into_vm(to: &str) -> bool { to.split('/').find(|component| !component.is_empty()) == Some("vm") } -impl Ctx<'_, '_> { - async fn get_arch( - &mut self, - uid: symbol_table::GlobalSymbol, - ) -> anyhow::Result<( - symbol_table::GlobalSymbol, - sync::DArc, - )> { - let uid = self.full_check_runner_uid(uid)?; +/// How a resolved runner id should be loaded into the archive cache. +enum ResolvedKind { + /// A packaged `name:hash` runner read from the runners directory. + Disk { + name: symbol_table::GlobalSymbol, + hash: symbol_table::GlobalSymbol, + }, + /// The current contract's runner, already preloaded into the cache. + Preloaded, + /// `chain:
::` — code blob read from a storage slot. + Chain { + address: calldata::Address, + on: public_abi::StorageType, + slot: crate::SlotID, + }, + /// `custom:` — a runner registered at runtime. + Custom { hash: symbol_table::GlobalSymbol }, +} + +/// A runner id resolved to its canonical cache key together with the way it +/// should be loaded. +struct Resolved { + id: symbol_table::GlobalSymbol, + kind: ResolvedKind, +} - let Some((runner_id, runner_hash)) = runners::verify_runner(uid.as_str()) else { +impl Ctx<'_, '_> { + fn resolve_runner(&self, id: symbol_table::GlobalSymbol) -> anyhow::Result { + let Some(parsed) = runners::parse_runner_id(id.as_str()) else { return Err(make_malformed_runner_error( "runner id doesn't match expected format", )); }; - let limiter = &self.vm.store.data_mut().limits; - - let new_arch = self - .supervisor - .runner_cache - .get_or_create( - uid, - || async { - let mut path = self.supervisor.runner_cache.runners_path().to_owned(); - runners::append_runner_subpath(runner_id, runner_hash, &mut path); - path.set_extension("tar"); - if !path.exists() { - anyhow::bail!("runner {} not found", uid); + match parsed { + runners::RunnerId::Contract => Ok(Resolved { + id: self.contract_id, + kind: ResolvedKind::Preloaded, + }), + runners::RunnerId::NameHash { name, hash } => { + let hash = if hash.as_str() == "test" || hash.as_str() == "latest" { + if !self.supervisor.shared_data.debug_mode { + log_warn!( + ":test/ :latest runner used in non-debug mode, this is not allowed" + ); + return Err(make_malformed_runner_error( + "runner id doesn't match expected format", + )); } + let new_latest = self.supervisor.runner_cache.get_latest(name); + log_info!(runner_id = name.as_str(), new_latest:? = new_latest; "resolving :latest runner"); + let Some(new_latest) = new_latest else { + return Err(make_malformed_runner_error( + "runner id doesn't match expected format", + )); + }; + new_latest + } else { + hash + }; - let data = util::mmap_file(&path) - .with_context(|| format!("memory mapping runner archive for {uid}"))?; - let data = bytes::Bytes::copy_from_slice(data.as_ref()); - runners::Archive::from_ustar(data) - .with_context(|| format!("parsing ustar archive for {uid}")) - }, - limiter, - ) - .await?; + if !self.supervisor.runner_cache.has_in_all(name, hash) { + anyhow::bail!("runner {}:{} not found", name, hash); + } - Ok((uid, new_arch)) - } + let mut canonical = name.as_str().to_owned(); + canonical.push(':'); + canonical.push_str(hash.as_str()); - fn full_check_runner_uid( - &mut self, - id: symbol_table::GlobalSymbol, - ) -> anyhow::Result { - if id.as_str() == "" { - return Ok(self.contract_id); + Ok(Resolved { + id: GlobalSymbol::new(canonical), + kind: ResolvedKind::Disk { name, hash }, + }) + } + runners::RunnerId::Chain { address, on, slot } => Ok(Resolved { + id: GlobalSymbol::from(runners::chain_canonical(address, on, slot)), + kind: ResolvedKind::Chain { address, on, slot }, + }), + runners::RunnerId::Custom { hash } => { + let mut canonical = String::from("custom:"); + canonical.push_str(hash.as_str()); + Ok(Resolved { + id: GlobalSymbol::from(canonical), + kind: ResolvedKind::Custom { hash }, + }) + } } - let Some((runner_id, runner_hash)) = runners::verify_runner(id.as_str()) else { - return Err(make_malformed_runner_error( - "runner id doesn't match expected format", - )); - }; - - let runner_id = GlobalSymbol::new(runner_id); + } - let runner_hash = if runner_hash == "test" || runner_hash == "latest" { - if !self.supervisor.shared_data.debug_mode { - log_warn!(":test/ :latest runner used in non-debug mode, this is not allowed"); - None - } else { - let new_latest = self.supervisor.runner_cache.get_latest(runner_id); - log_info!(runner_id = runner_id.as_str(), new_latest:? = new_latest; "resolving :latest runner"); - new_latest + async fn get_arch( + &mut self, + resolved: Resolved, + ) -> anyhow::Result<( + symbol_table::GlobalSymbol, + sync::DArc, + )> { + let Resolved { id, kind } = resolved; + + let limiter = self.vm.store.data_mut().limits.clone(); + let cache = &self.supervisor.runner_cache; + + let new_arch = match kind { + ResolvedKind::Disk { name, hash } => { + cache + .get_or_create( + id, + || async { + let mut path = cache.runners_path().to_owned(); + runners::append_runner_subpath(name.as_str(), hash.as_str(), &mut path); + path.set_extension("tar"); + if !path.exists() { + anyhow::bail!("runner {} not found", id); + } + + let data = util::mmap_file(&path).with_context(|| { + format!("memory mapping runner archive for {id}") + })?; + let data = bytes::Bytes::copy_from_slice(data.as_ref()); + runners::Archive::from_ustar(data) + .with_context(|| format!("parsing ustar archive for {id}")) + }, + &limiter, + ) + .await? + } + ResolvedKind::Preloaded => { + cache + .get_or_create( + id, + || async { anyhow::bail!("runner {} is not preloaded", id) }, + &limiter, + ) + .await? + } + ResolvedKind::Chain { address, on, slot } => { + let supervisor = self.supervisor; + cache + .get_or_create( + id, + || async { + let mut storage = rt::vm::storage::Storage::new( + address, + supervisor.get_storage_limiter(), + crate::wasi::genlayer_sdk::StorageHostHolder( + supervisor.host.clone(), + crate::wasi::genlayer_sdk::ReadToken { + account: address, + mode: on, + }, + ), + ); + let code = storage + .read_code_at(slot, &limiter) + .await + .with_context(|| format!("reading chain runner code for {id}"))?; + runners::parse(bytes::Bytes::from(code)) + .with_context(|| format!("parsing chain runner for {id}")) + }, + &limiter, + ) + .await? + } + ResolvedKind::Custom { hash } => { + let supervisor = self.supervisor; + cache + .get_or_create( + id, + || async { + supervisor + .get_custom_runner(hash) + .ok_or_else(|| anyhow::anyhow!("custom runner {} not found", id)) + }, + &limiter, + ) + .await? } - } else { - Some(GlobalSymbol::new(runner_hash)) - }; - - let Some(runner_hash) = runner_hash else { - return Err(make_malformed_runner_error( - "runner id doesn't match expected format", - )); }; - if !self - .supervisor - .runner_cache - .has_in_all(runner_id, runner_hash) - { - anyhow::bail!("runner {}:{} not found", runner_id, runner_hash); - } - - let mut new_id = runner_id.as_str().to_owned(); - new_id.push(':'); - new_id.push_str(runner_hash.as_str()); - - Ok(symbol_table::GlobalSymbol::new(new_id)) + Ok((id, new_arch)) } fn load_modules( @@ -431,22 +519,23 @@ impl Ctx<'_, '_> { runner: uid, action, } => { - let (uid, new_arch) = self.get_arch(*uid).await?; + let resolved = self.resolve_runner(*uid)?; + let (uid, new_arch) = self.get_arch(resolved).await?; Box::pin(self.apply(action, uid, &new_arch)) .await .with_context(|| format!("With {uid}")) } InitAction::Depends(uid) => { - let uid = self.full_check_runner_uid(*uid)?; + let resolved = self.resolve_runner(*uid)?; - if !self.visited.insert(uid) { + if !self.visited.insert(resolved.id) { return Ok(None); } - log_trace!(uid = uid; "adding dependency"); + log_trace!(uid = resolved.id; "adding dependency"); - let (uid, new_arch) = self.get_arch(uid).await?; + let (uid, new_arch) = self.get_arch(resolved).await?; let new_action = new_arch .get_actions() diff --git a/executor/src/rt/supervisor/mod.rs b/executor/src/rt/supervisor/mod.rs index 529c2f499..f2a7b818a 100644 --- a/executor/src/rt/supervisor/mod.rs +++ b/executor/src/rt/supervisor/mod.rs @@ -76,6 +76,10 @@ pub struct Supervisor { runner_cache: runners::cache::Reader, wasm_mod_cache: WasmModuleCache, + /// Runners registered at runtime via `gl_call`, looked up by the + /// `custom:` runner id. Empty until a contract registers one. + custom_runners: dashmap::DashMap, + pub(crate) engines: rt::DetNondet, pub(crate) host: Arc, } @@ -221,6 +225,23 @@ impl Supervisor { rt::vm::storage::Limiter::new(self.shared_data.gep(|x| &x.data_fees_limit)) } + pub fn get_custom_runner(&self, hash: GlobalSymbol) -> Option { + self.custom_runners.get(&hash).map(|r| r.clone()) + } + + /// Registers a runner archive under `custom:`. Returns the canonical + /// runner id it can be referenced by. + pub fn register_custom_runner( + &self, + hash: GlobalSymbol, + archive: runners::Archive, + ) -> GlobalSymbol { + self.custom_runners.insert(hash, archive); + let mut id = String::from("custom:"); + id.push_str(hash.as_str()); + GlobalSymbol::from(id) + } + pub fn start(config: &config::Config, ctor: Ctor) -> anyhow::Result> { let my_cache_dir = runners::cache::get_cache_dir(&config.cache_dir).ok(); @@ -284,6 +305,7 @@ impl Supervisor { cache_dir: my_cache_dir, wasm_modules_cache: sync::CacheMap::new(), }, + custom_runners: dashmap::DashMap::new(), host: Arc::new(ctor.multi_host), engines, }); @@ -375,7 +397,17 @@ pub async fn apply_contract_actions( .message .contract_address; - let contract_id = runners::get_runner_of_contract(contract_address); + let contract_state = vm + .vm_base + .store + .data() + .genlayer_ctx + .genlayer_sdk + .data + .conf + .state_mode; + + let contract_id = runners::get_runner_of_contract(contract_address, contract_state); let limiter = vm.vm_base.store.data_mut().limits.clone(); diff --git a/executor/src/rt/vm/storage.rs b/executor/src/rt/vm/storage.rs index eaa4bf31c..dfa76207e 100644 --- a/executor/src/rt/vm/storage.rs +++ b/executor/src/rt/vm/storage.rs @@ -412,7 +412,14 @@ impl Storage { limiter: &rt::memlimiter::Limiter, ) -> anyhow::Result> { let code_slot = SlotID::ZERO.indirection(root_offsets::CODE); + self.read_code_at(code_slot, limiter).await + } + pub async fn read_code_at( + &mut self, + code_slot: SlotID, + limiter: &rt::memlimiter::Limiter, + ) -> anyhow::Result> { let mut len_buf = [0; 4]; self.read(code_slot, 0, &mut len_buf).await?; let code_size = u32::from_le_bytes(len_buf); diff --git a/executor/src/runners/mod.rs b/executor/src/runners/mod.rs index ebb0495b8..cb6e09c12 100644 --- a/executor/src/runners/mod.rs +++ b/executor/src/runners/mod.rs @@ -23,11 +23,125 @@ pub fn append_runner_subpath(id: &str, hash: &str, path: &mut std::path::PathBuf path.push(&hash[2..]); } -pub fn get_runner_of_contract(address: calldata::Address) -> symbol_table::GlobalSymbol { - let mut contract_id = String::from("on_chain:0x"); - contract_id.push_str(&hex::encode(address.raw())); +/// A parsed runner id. Runner ids come in the following forms: +/// +/// - `name:hash` — a packaged runner identified by its human readable name and +/// content hash (in debug mode `hash` may also be `test`/`latest`). +/// - `contract` — the runner of the contract that is currently being executed. +/// - `chain:
::` — read the runner code blob from a storage +/// slot of an arbitrary contract. `address` is a `0x`-prefixed 20 byte hex +/// address, `a`/`f` selects accepted (latest non final) / finalized state and +/// `slot` is a `0x`-prefixed 32 byte hex slot id. +/// - `custom:` — a runner registered at runtime, looked up by its hash. +pub enum RunnerId { + NameHash { + name: symbol_table::GlobalSymbol, + hash: symbol_table::GlobalSymbol, + }, + Contract, + Chain { + address: calldata::Address, + on: crate::public_abi::StorageType, + slot: crate::SlotID, + }, + Custom { + hash: symbol_table::GlobalSymbol, + }, +} + +fn is_hash_char(c: char) -> bool { + c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '=' +} + +fn parse_hex_fixed(s: &str) -> Option<[u8; N]> { + let s = s.strip_prefix("0x").unwrap_or(s); + if s.len() != N * 2 { + return None; + } + let mut out = [0u8; N]; + hex::decode_to_slice(s, &mut out).ok()?; + Some(out) +} + +pub fn parse_runner_id(id: &str) -> Option { + if id == "contract" { + return Some(RunnerId::Contract); + } + + if let Some(rest) = id.strip_prefix("chain:") { + let mut it = rest.split(':'); + let address = it.next()?; + let on = it.next()?; + let slot = it.next()?; + if it.next().is_some() { + return None; + } + + let address = calldata::Address::from(parse_hex_fixed::<20>(address)?); + let on = match on { + "a" => crate::public_abi::StorageType::LatestNonFinal, + "f" => crate::public_abi::StorageType::LatestFinal, + _ => return None, + }; + let slot = crate::SlotID::from_bytes(parse_hex_fixed::<32>(slot)?); + + return Some(RunnerId::Chain { address, on, slot }); + } + + if let Some(rest) = id.strip_prefix("custom:") { + if rest.is_empty() || !rest.chars().all(is_hash_char) { + return None; + } + return Some(RunnerId::Custom { + hash: symbol_table::GlobalSymbol::new(rest), + }); + } + + let (name, hash) = id.split_once(':')?; + if name.is_empty() || hash.is_empty() { + return None; + } + for c in name.chars() { + if !c.is_ascii_alphanumeric() && c != '-' && c != '_' { + log_warn!("character `{c}` is not allowed in runner id"); + return None; + } + } + if !hash.chars().all(is_hash_char) { + return None; + } + Some(RunnerId::NameHash { + name: symbol_table::GlobalSymbol::new(name), + hash: symbol_table::GlobalSymbol::new(hash), + }) +} + +/// Canonical textual form of a [`RunnerId::Chain`]. Used as the cache key so +/// that an explicit `chain:` reference and the current `contract` resolve to the +/// same entry when they point at the same address/state/slot. +pub fn chain_canonical( + address: calldata::Address, + on: crate::public_abi::StorageType, + slot: crate::SlotID, +) -> String { + let on = match on { + crate::public_abi::StorageType::LatestFinal => 'f', + _ => 'a', + }; + format!( + "chain:0x{}:{}:0x{}", + hex::encode(address.raw()), + on, + hex::encode(slot.raw()) + ) +} - symbol_table::GlobalSymbol::from(contract_id) +pub fn get_runner_of_contract( + address: calldata::Address, + state: crate::public_abi::StorageType, +) -> symbol_table::GlobalSymbol { + let slot = crate::SlotID::ZERO.indirection(crate::host::message::root_offsets::CODE); + symbol_table::GlobalSymbol::from(chain_canonical(address, state, slot)) } pub struct ArchiveCache { diff --git a/executor/src/runners/ustar.rs b/executor/src/runners/ustar.rs index ebb93c9b9..e7ac91ee3 100644 --- a/executor/src/runners/ustar.rs +++ b/executor/src/runners/ustar.rs @@ -1,5 +1,6 @@ use std::collections::BTreeMap; +#[derive(Clone)] pub struct Archive { pub data: BTreeMap, pub total_size: u32, diff --git a/runners/genlayer-py-std/default.nix b/runners/genlayer-py-std/default.nix index f6c48c7dd..d190bd5d6 100644 --- a/runners/genlayer-py-std/default.nix +++ b/runners/genlayer-py-std/default.nix @@ -58,7 +58,7 @@ in expr = { Seq = [ - { With = { runner = ""; action = { MapFile = { file = "file"; to = "/contract.py"; }; }; }; } + { With = { runner = "contract"; action = { MapFile = { file = "file"; to = "/contract.py"; }; }; }; } ] ++ middle_runner_seq; }; })) ++ @@ -68,7 +68,7 @@ in expr = { Seq = [ - { With = { runner = ""; action = { MapFile = { file = "contract/"; to = "/contract/"; }; }; }; } + { With = { runner = "contract"; action = { MapFile = { file = "contract/"; to = "/contract/"; }; }; }; } ] ++ middle_runner_seq; }; })) ++ diff --git a/runners/support/versions/current.nix b/runners/support/versions/current.nix index 77f212413..d72b3a986 100644 --- a/runners/support/versions/current.nix +++ b/runners/support/versions/current.nix @@ -55,7 +55,7 @@ let wrappers = { __prefix = ""; py-genlayer = { - hash = "sha256-kG+3MeXEXyVV9vbJL8AuffoMoQav+wbePKmdVCa2Jv8="; + hash = "sha256-4lw3JWpiiV7MBDuaGky2Hthd5NZZc+QAHvbLsmMczkI="; depends = [ cpython pyLibs.cloudpickle @@ -63,7 +63,7 @@ let ]; }; py-genlayer-multi = { - hash = "sha256-5C1f9KTf4MXZL3cZflwsy2fhJq7icS4yfHjZxxEyhks="; + hash = "sha256-YpyBSONfxM/ZZ7iRy+e2Su1yN/84W8bP1tl4c8t/fos="; depends = [ cpython pyLibs.cloudpickle From cedfce3443b626f4de1ac8d359b2fc912d476b96 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Fri, 19 Jun 2026 22:18:40 +0900 Subject: [PATCH 002/124] =?UTF-8?q?chore(build):=20switch=20runners=20to?= =?UTF-8?q?=20dev=20mode=20(hashes=3Dtest)=20=F0=9F=9A=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- runners/support/versions/current.nix | 20 ++++++++++---------- runners/support/versions/dev-mode.nix | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/runners/support/versions/current.nix b/runners/support/versions/current.nix index d72b3a986..c2f5742ca 100644 --- a/runners/support/versions/current.nix +++ b/runners/support/versions/current.nix @@ -8,7 +8,7 @@ let __prefix = "models-"; all-MiniLM-L6-v2 = { - hash = "sha256-OlZQmCyKA+ct9hV4G12vSRUYUYB2S1CdDjIG2ueaOjQ="; + hash = "test"; }; }; @@ -16,22 +16,22 @@ let __prefix = "py-lib-"; cloudpickle = { - hash = "sha256-X/SQxZDU/Ep9D5ptzccqMiewgUh6mtt3vMyA+ZnqrHA="; + hash = "test"; }; protobuf = { - hash = "sha256-i0mGEqZ5XvoYCK5EZLZe48BltX8UYDxsiBQ8wJDratE="; + hash = "test"; }; word_piece_tokenizer = { - hash = "sha256-3T57N4bs1eSBaudAg0Dwi87d7kbu+anEYlGFH4Q3ujA="; + hash = "test"; }; genlayer-std = { - hash = "sha256-cN/I/NE1rffwlrhd3o6Xso45hB7I3yLeRRwpMnfy+II="; + hash = "test"; }; genlayer-embeddings = { - hash = "sha256-y86+lwso1yaosRcyj4wI92YQfj2JNvn0BRBYLG2IpNU="; + hash = "test"; depends = [ models.all-MiniLM-L6-v2 @@ -42,20 +42,20 @@ let }; cpython = { - hash = "sha256-qYd0fAfKBdFwG9qR+AsXjS8gJFm11Z47vsnMEyf0SzM="; + hash = "test"; depends = [ softfloat ]; }; softfloat = { - hash = "sha256-aR7i/mGXm+x7ofoL7iJ1zUHsVyqkAsZG0mQ/Lj1+l4c="; + hash = "test"; }; wrappers = { __prefix = ""; py-genlayer = { - hash = "sha256-4lw3JWpiiV7MBDuaGky2Hthd5NZZc+QAHvbLsmMczkI="; + hash = "test"; depends = [ cpython pyLibs.cloudpickle @@ -63,7 +63,7 @@ let ]; }; py-genlayer-multi = { - hash = "sha256-YpyBSONfxM/ZZ7iRy+e2Su1yN/84W8bP1tl4c8t/fos="; + hash = "test"; depends = [ cpython pyLibs.cloudpickle diff --git a/runners/support/versions/dev-mode.nix b/runners/support/versions/dev-mode.nix index c508d5366..27ba77dda 100644 --- a/runners/support/versions/dev-mode.nix +++ b/runners/support/versions/dev-mode.nix @@ -1 +1 @@ -false +true From 49b40ba8947e22062ff15abe8c6e499345c07905 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Fri, 19 Jun 2026 22:47:20 +0900 Subject: [PATCH 003/124] =?UTF-8?q?feat(executor):=20add=20register=5Frunn?= =?UTF-8?q?er=20gl=5Fcall=20for=20custom=20runners=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...11. runner ids and runtime registration.md | 95 +++++++++++++++++++ .../03-wasi_genlayer_sdk/02-gl_call.rst | 25 +++++ doc/website/src/spec/03-vm/05-permissions.rst | 8 ++ executor/crates/sdk-rs/src/abi/gl_call.rs | 5 + executor/src/exe/run.rs | 6 +- executor/src/lib.rs | 1 + executor/src/runners/mod.rs | 8 ++ executor/src/wasi/base.rs | 1 + executor/src/wasi/genlayer_sdk.rs | 52 ++++++++++ modules/implementation/src/manager/run.rs | 2 +- .../src/genlayer/vm/__init__.py | 21 ++++ .../stable/runners/register-runner.0.stdout | 2 + .../stable/runners/register-runner.jsonnet | 3 + tests/cases/stable/runners/register-runner.py | 7 ++ 14 files changed, 232 insertions(+), 4 deletions(-) create mode 100644 doc/adr/011. runner ids and runtime registration.md create mode 100644 tests/cases/stable/runners/register-runner.0.stdout create mode 100644 tests/cases/stable/runners/register-runner.jsonnet create mode 100644 tests/cases/stable/runners/register-runner.py diff --git a/doc/adr/011. runner ids and runtime registration.md b/doc/adr/011. runner ids and runtime registration.md new file mode 100644 index 000000000..032cc0955 --- /dev/null +++ b/doc/adr/011. runner ids and runtime registration.md @@ -0,0 +1,95 @@ +# ADR-011: Runner IDs and Runtime Runner Registration + +## Status + +- **Status**: Accepted +- **Date**: 2026-06-19 + +## Context + +[ADR-002](<002. code loading.md>) introduced runners and identified them by a +`:` string, with a special `` literal for the +contract currently being executed and an internal `on_chain:0x
` id used +when loading a contract's own runner from its code. + +This scheme is limiting: + +- The `` literal and the `on_chain:` id were implementation details + that were never specified, so contracts could not reference runner code stored + on chain in a documented, stable way. +- There is no way to load runner code from an arbitrary contract's storage, which + blocks reuse of code parts between contracts (see research + [GVM-231](https://linear.app/genlayer-labs/issue/GVM-231)). +- There is no way for a contract to provide runner code at runtime (e.g. to build + a more capable / user-provided execution environment) — the runner set was + fixed at load time. + +## Decision + +Rework runner ids into four explicit, specified forms (parsed in +`executor/src/runners`): + +1. `name:hash` — a packaged runner by human readable name (`[a-zA-Z0-9_-]+`) and + archive hash. In debug mode the hash may be `test`/`latest`. Unchanged. +2. `contract` — the runner of the contract currently being executed. Replaces the + old, undocumented `` literal. +3. `chain:
::` — load a runner code blob directly from a + storage slot of an arbitrary contract: `
` is a `0x` 20 byte hex + address, `a`/`f` selects accepted (latest non final) / finalized state, and + `` is a `0x` 32 byte hex slot id. The current contract's runner is the + canonical `chain:` id pointing at itself and the code slot, so `contract` and + an explicit self reference deduplicate in the cache. +4. `custom:` — a runner registered at runtime, looked up in an in-memory map + keyed by ``. + +`contract`, `chain` and `custom` are reserved prefixes and cannot be used as +human readable runner names. + +Add a `gl_call` `RegisterRunner { code: Bytes }` that parses `code` as a runner +archive, charges its size against the memory limit and stores it under +`custom:`, where `` is a SHA3-256 of `code`. It returns the resulting +runner id. It is allowed only in deterministic mode and only when the contract +holds the new `register_runners` permission (permission char `u`). A friendly +`genlayer.vm.register_runner(code) -> str` wrapper is exposed in the Python SDK. + +## Consequences + +### Positive + +- Runner ids are fully specified and uniform; `contract`/`chain`/`custom` are + first-class instead of hidden literals. +- Contracts can load code parts from other contracts' storage on chain. +- Contracts can extend their execution environment with runtime-provided code. + +### Negative + +- `` is no longer accepted; runners embedding it must be rebuilt to use + `contract` (done for the bundled `py-genlayer` wrappers). +- `chain` and `custom` become reserved prefixes, slightly shrinking the space of + valid human readable runner names. + +### Neutral + +- The `custom:` map is per-execution and starts empty; registered runners do not + persist across executions. + +## Alternatives Considered + +- **Keep ``/`on_chain:` internal-only**: rejected because contracts + need a documented way to reference on-chain and current-contract runners. +- **A dedicated `exec` gl_call that replaces the current VM with a new one + carrying user code** (GVM-231 idea A): rejected for now because propagating the + extended runner into sub-sub-VMs is not obvious; registering under `custom:` and + referencing it from ordinary `Depends`/`With` composes with the existing loader. + +## Implementation Notes + +- Parsing/canonicalization lives in `executor/src/runners/mod.rs` + (`parse_runner_id`, `chain_canonical`, `custom_runner_hash`); resolution and + loading in `executor/src/rt/supervisor/actions.rs`. +- `chain:` reads code via a fresh `Storage` pointed at the target address/state + and `read_code_at(slot)`. +- The `custom:` map lives on `Supervisor` (`register_custom_runner` / + `get_custom_runner`). +- Spec: `doc/schemas/runners.json` (`runner-id` type), + `doc/website/src/spec/.../02-gl_call.rst` and `.../03-vm/05-permissions.rst`. diff --git a/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst b/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst index 9b8621314..48e5937a3 100644 --- a/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst +++ b/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst @@ -186,6 +186,31 @@ Payload Creates isolated VM instance. See :ref:`gvm-permissions` for permission inheritance details. +``RegisterRunner`` Message +-------------------------- + +Registers a runner archive at runtime, making it available under the +``custom:`` runner id. The ```` is +derived from the supplied ``code`` and the parsed archive is charged against the +memory limit. Returns the resulting runner id (calldata-encoded string). + +Payload +~~~~~~~ + +.. code-block:: + + { + "RegisterRunner": { + "code": Bytes // runner archive (ustar/zip or commented text) + } + } + +Requirements +~~~~~~~~~~~~ + +#. :ref:`gvm-perm-deterministic` +#. :ref:`gvm-perm-register-runners` + ``WebRender`` Message --------------------- diff --git a/doc/website/src/spec/03-vm/05-permissions.rst b/doc/website/src/spec/03-vm/05-permissions.rst index ec7e18ada..0301a9547 100644 --- a/doc/website/src/spec/03-vm/05-permissions.rst +++ b/doc/website/src/spec/03-vm/05-permissions.rst @@ -51,6 +51,14 @@ Requires :ref:`gvm-perm-deterministic` as well. Allows spawning :ref:`gvm-def-non-det-mode` :term:`sub-VM` instances via ``RunNondet``. +.. _gvm-perm-register-runners: + +``register_runners`` +-------------------- + +Allows registering runner archives at runtime via ``RegisterRunner``, making +them available under ``custom:`` runner ids. Requires :ref:`gvm-perm-deterministic` as well. + Permission Changes on Sub-VM Creation -------------------------------------- diff --git a/executor/crates/sdk-rs/src/abi/gl_call.rs b/executor/crates/sdk-rs/src/abi/gl_call.rs index 0a2ce6992..68f3059d4 100644 --- a/executor/crates/sdk-rs/src/abi/gl_call.rs +++ b/executor/crates/sdk-rs/src/abi/gl_call.rs @@ -576,6 +576,11 @@ pub enum Message { allow_write_ops: bool, }, + RegisterRunner { + #[cfg_attr(feature = "arbitrary", arbitrary(with = crate::abi::arb::arb_bytes))] + code: Bytes, + }, + WebRender(web_iface::RenderPayload), WebRequest(web_iface::RequestPayload), ExecPrompt(llm_iface::PromptPayload), diff --git a/executor/src/exe/run.rs b/executor/src/exe/run.rs index 17ab463ab..114f61b89 100644 --- a/executor/src/exe/run.rs +++ b/executor/src/exe/run.rs @@ -34,8 +34,8 @@ pub struct Args { sync: bool, #[clap( long, - default_value = "rwscn", - help = "r?w?s?c?n?, read/write/send messages/call contracts/spawn nondet" + default_value = "rwscnu", + help = "r?w?s?c?n?u?, read/write/send messages/call contracts/spawn nondet/register runners" )] permissions: String, #[clap(long, help = "override LLM module address from config")] @@ -222,7 +222,7 @@ pub fn handle(args: Args, mut config: config::Config) -> Result<()> { } let mut perm_size = 0; - for perm in ["r", "w", "s", "c", "n"] { + for perm in ["r", "w", "s", "c", "n", "u"] { if args.permissions.contains(perm) { perm_size += 1; } diff --git a/executor/src/lib.rs b/executor/src/lib.rs index e142e41ee..b967d92e6 100644 --- a/executor/src/lib.rs +++ b/executor/src/lib.rs @@ -187,6 +187,7 @@ pub async fn run_with_impl( can_send_messages: permissions.contains("s"), can_call_others: permissions.contains("c"), can_spawn_nondet: permissions.contains("n"), + can_register_runners: permissions.contains("u"), state_mode: crate::public_abi::StorageType::Default, }, message_data: ExtendedMessage { diff --git a/executor/src/runners/mod.rs b/executor/src/runners/mod.rs index cb6e09c12..242a514e2 100644 --- a/executor/src/runners/mod.rs +++ b/executor/src/runners/mod.rs @@ -136,6 +136,14 @@ pub fn chain_canonical( ) } +/// Derives the hash component of a `custom:` runner id from its code. +pub fn custom_runner_hash(code: &[u8]) -> symbol_table::GlobalSymbol { + use sha3::Digest as _; + let mut digest = sha3::Sha3_256::new(); + digest.update(code); + symbol_table::GlobalSymbol::from(hex::encode(digest.finalize())) +} + pub fn get_runner_of_contract( address: calldata::Address, state: crate::public_abi::StorageType, diff --git a/executor/src/wasi/base.rs b/executor/src/wasi/base.rs index 88844f627..dfe1dad84 100644 --- a/executor/src/wasi/base.rs +++ b/executor/src/wasi/base.rs @@ -11,6 +11,7 @@ pub struct Config { pub can_spawn_nondet: bool, pub can_send_messages: bool, pub can_call_others: bool, + pub can_register_runners: bool, pub state_mode: public_abi::StorageType, } diff --git a/executor/src/wasi/genlayer_sdk.rs b/executor/src/wasi/genlayer_sdk.rs index e97fd00a4..64c7dfa24 100644 --- a/executor/src/wasi/genlayer_sdk.rs +++ b/executor/src/wasi/genlayer_sdk.rs @@ -714,6 +714,7 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { can_spawn_nondet: my_conf.can_spawn_nondet, can_call_others: my_conf.can_call_others, can_send_messages: my_conf.can_send_messages, + can_register_runners: my_conf.can_register_runners, state_mode: state, }, message_data: ExtendedMessage { @@ -1344,6 +1345,7 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { data, allow_write_ops, } => self.sandbox(data, allow_write_ops).await, + gl_call::Message::RegisterRunner { code } => self.register_runner(code).await, gl_call::Message::Trace(message) => self.gl_call_trace(message).await, } } @@ -1579,6 +1581,54 @@ impl ContextVFS<'_> { } } + async fn register_runner( + &mut self, + code: bytes::Bytes, + ) -> Result { + if !self.context.data.conf.is_deterministic { + return Err(generated::types::Errno::Forbidden.into()); + } + if !self.context.data.conf.can_register_runners { + return Err(generated::types::Errno::Forbidden.into()); + } + + let hash = crate::runners::custom_runner_hash(&code); + + let archive = crate::runners::parse(code) + .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?; + + let is_det = self.context.data.conf.is_deterministic; + if !self + .context + .data + .supervisor + .limiter + .get(is_det) + .consume(archive.total_size) + { + return Err(generated::types::Error::trap(crate::anyhow_to_wasmtime( + rt::errors::VMError(abi::consts::VmError::oom().ram().val(), None).into(), + ))); + } + + let id = self + .context + .data + .supervisor + .register_custom_runner(hash, archive); + + let data = calldata::encode(&calldata::Value::Str(id.as_str().to_owned())); + Ok(generated::types::Fd::from( + self.vfs + .place_content(vfs::FileContents { + contents: bytes::Bytes::from(data), + pos: 0, + release_memory: true, + }) + .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?, + )) + } + async fn run_nondet( &mut self, data_leader: bytes::Bytes, @@ -1746,6 +1796,7 @@ impl ContextVFS<'_> { can_spawn_nondet: false, can_call_others: false, can_send_messages: false, + can_register_runners: false, state_mode: public_abi::StorageType::Default, }, message_data, @@ -1833,6 +1884,7 @@ impl ContextVFS<'_> { can_spawn_nondet: false, can_call_others: false, can_send_messages: zelf_conf.can_send_messages & allow_write_ops, + can_register_runners: false, state_mode: zelf_conf.state_mode, }, message_data, diff --git a/modules/implementation/src/manager/run.rs b/modules/implementation/src/manager/run.rs index a92cf63c2..c23bd8863 100644 --- a/modules/implementation/src/manager/run.rs +++ b/modules/implementation/src/manager/run.rs @@ -427,7 +427,7 @@ fn default_message_fee_allocation() -> Vec String { - "rwscn".to_owned() + "rwscnu".to_owned() } impl Request { diff --git a/runners/genlayer-py-std/src/genlayer/vm/__init__.py b/runners/genlayer-py-std/src/genlayer/vm/__init__.py index 447941910..a5183379a 100644 --- a/runners/genlayer-py-std/src/genlayer/vm/__init__.py +++ b/runners/genlayer-py-std/src/genlayer/vm/__init__.py @@ -20,6 +20,7 @@ 'Result', 'trace', 'trace_time_micro', + 'register_runner', 'ABI', ) @@ -334,3 +335,23 @@ def trace_time_micro() -> int: }, lambda x: typing.cast(int, calldata.decode(x)), ).get() + + +def register_runner(code: collections.abc.Buffer) -> str: + """ + Registers a runner archive at runtime and returns its ``custom:`` id. + + The returned id can be referenced from ``Depends``/``With`` actions of other + runners. Requires deterministic mode and the ``register_runners`` permission. + + :param code: runner archive bytes (ustar/zip or commented text) + :return: the ``custom:`` runner id + """ + return gl_call.gl_call_generic( + { + 'RegisterRunner': { + 'code': code, + }, + }, + lambda x: typing.cast(str, calldata.decode(x)), + ).get() diff --git a/tests/cases/stable/runners/register-runner.0.stdout b/tests/cases/stable/runners/register-runner.0.stdout new file mode 100644 index 000000000..4bc51f8c2 --- /dev/null +++ b/tests/cases/stable/runners/register-runner.0.stdout @@ -0,0 +1,2 @@ +custom:f5431a053008f57effd6036d17f8c39439ae6511f407dcdd62dbcf27ee4d4b4c +executed with `Return(null)` diff --git a/tests/cases/stable/runners/register-runner.jsonnet b/tests/cases/stable/runners/register-runner.jsonnet new file mode 100644 index 000000000..11fce59e3 --- /dev/null +++ b/tests/cases/stable/runners/register-runner.jsonnet @@ -0,0 +1,3 @@ +local simple = import 'templates/simple_deploy.jsonnet'; +local util = import 'templates/util.jsonnet'; +{entry: util.addPaths([simple.run('${jsonnetDir}/register-runner.py') {stable_hash: false}])} diff --git a/tests/cases/stable/runners/register-runner.py b/tests/cases/stable/runners/register-runner.py new file mode 100644 index 000000000..8539e9bf3 --- /dev/null +++ b/tests/cases/stable/runners/register-runner.py @@ -0,0 +1,7 @@ +# { "Depends": "py-genlayer:test" } + +from genlayer.vm import register_runner + +code = b'# { "Depends": "py-genlayer:test" }\nexit(0)\n' +print(register_runner(code)) +exit(0) From 2ba28237954c105a6bf4ed1c4f703946dffaeeaa Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Fri, 19 Jun 2026 22:48:07 +0900 Subject: [PATCH 004/124] =?UTF-8?q?feat(wasi):=20per-permission=20sandbox?= =?UTF-8?q?=20allow=20flags=20(write/send/register)=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/skills/branch-review/SKILL.md | 41 +++++++++++++++++++ .../03-wasi_genlayer_sdk/02-gl_call.rst | 6 ++- doc/website/src/spec/03-vm/05-permissions.rst | 5 ++- executor/crates/sdk-rs/src/abi/gl_call.rs | 4 +- executor/src/wasi/genlayer_sdk.rs | 24 ++++++++--- .../src/genlayer/vm/__init__.py | 21 ++++++++-- .../stable/py/balances/sandbox_overspend.py | 4 +- .../stable/py/balances/sandbox_overspend_2.py | 2 +- .../stable/py/sandbox/det/sandbox_write.py | 2 +- 9 files changed, 90 insertions(+), 19 deletions(-) create mode 100644 .claude/skills/branch-review/SKILL.md diff --git a/.claude/skills/branch-review/SKILL.md b/.claude/skills/branch-review/SKILL.md new file mode 100644 index 000000000..9561a21dc --- /dev/null +++ b/.claude/skills/branch-review/SKILL.md @@ -0,0 +1,41 @@ +--- +name: branch-review +description: Reviews the current GenVM branch by fanning out three specialized review agents (spec, security, implementation). Use when asked to "review this branch", "review the PR", or do a full code review of a diff. +--- + +# Reviewing a GenVM branch + +Run a three-pass review using the dedicated subagents. Launch all three **in a +single message** (one Agent tool call each) so they run concurrently — they are +independent and read-only. + +| Pass | Agent (`subagent_type`) | Owns | +| --- | --- | --- | +| Spec | `spec-reviewer` | ADR/proposal quality; spec & schema soundness as documents | +| Security | `security-reviewer` | permissions, sandbox propagation, limiter/consume-once, parsing, exfiltration | +| Implementation | `implementation-reviewer` | code-vs-spec drift, AI slop, duplicated logic, doc completeness, useless comments | + +## Baseline + +All three diff against the active **dev** branch, not `main` (default +`v0.3-dev`; confirm with `git branch -a | grep dev`). Pass the base in the prompt +if the user named one. Do NOT treat the dev-mode / `hashes=test` build state as a +finding — it is intentional. + +## Procedure + +1. Confirm the base branch (default `v0.3-dev`). +2. In one message, spawn `spec-reviewer`, `security-reviewer`, and + `implementation-reviewer`, each told the base branch and any extra scope the + user gave. +3. Synthesize their three reports into one review: lead with the merge verdict, + then a **Blocking** section and a **Nits** section, attributing findings to + their pass. De-duplicate overlaps (e.g. a duplicated-logic issue both security + and implementation raise) into a single entry. + +## Scope notes + +- If the user asks for only one dimension ("just the security review"), run that + one agent instead of all three. +- Each agent is read-only; none will edit code. If the user wants fixes after the + review, that is a separate, explicit follow-up. diff --git a/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst b/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst index 48e5937a3..e8bf453d5 100644 --- a/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst +++ b/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst @@ -179,8 +179,10 @@ Payload { "Sandbox": { - "data": Bytes, // Code/data for sandbox execution - "allow_write_ops": Bool // Whether to allow write operations + "data": Bytes, // Code/data for sandbox execution + "allow_write_storage": Bool, // Whether to allow storage writes + "allow_send_messages": Bool, // Whether to allow sending messages + "allow_register_runners": Bool // Whether to allow registering runners } } diff --git a/doc/website/src/spec/03-vm/05-permissions.rst b/doc/website/src/spec/03-vm/05-permissions.rst index 0301a9547..111b74846 100644 --- a/doc/website/src/spec/03-vm/05-permissions.rst +++ b/doc/website/src/spec/03-vm/05-permissions.rst @@ -90,7 +90,8 @@ The sandboxed :term:`sub-VM` has: - :ref:`gvm-perm-deterministic` is **inherited** - :ref:`gvm-perm-read-storage` is **inherited** -- :ref:`gvm-perm-write-storage` is **inherited** if ``allow_write_ops`` is set, otherwise **disabled** +- :ref:`gvm-perm-write-storage` is **inherited** if ``allow_write_storage`` is set, otherwise **disabled** - :ref:`gvm-perm-spawn-nondet` is **disabled** - :ref:`gvm-perm-call-others` is **disabled** -- :ref:`gvm-perm-send-messages` is **inherited** if ``allow_write_ops`` is set, otherwise **disabled** +- :ref:`gvm-perm-send-messages` is **inherited** if ``allow_send_messages`` is set, otherwise **disabled** +- :ref:`gvm-perm-register-runners` is **inherited** if ``allow_register_runners`` is set, otherwise **disabled** diff --git a/executor/crates/sdk-rs/src/abi/gl_call.rs b/executor/crates/sdk-rs/src/abi/gl_call.rs index 68f3059d4..cb0960444 100644 --- a/executor/crates/sdk-rs/src/abi/gl_call.rs +++ b/executor/crates/sdk-rs/src/abi/gl_call.rs @@ -573,7 +573,9 @@ pub enum Message { #[cfg_attr(feature = "arbitrary", arbitrary(with = crate::abi::arb::arb_bytes))] data: Bytes, - allow_write_ops: bool, + allow_write_storage: bool, + allow_send_messages: bool, + allow_register_runners: bool, }, RegisterRunner { diff --git a/executor/src/wasi/genlayer_sdk.rs b/executor/src/wasi/genlayer_sdk.rs index 64c7dfa24..2e7e71da9 100644 --- a/executor/src/wasi/genlayer_sdk.rs +++ b/executor/src/wasi/genlayer_sdk.rs @@ -1343,8 +1343,18 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { } => self.run_nondet(data_leader, data_validator).await, gl_call::Message::Sandbox { data, - allow_write_ops, - } => self.sandbox(data, allow_write_ops).await, + allow_write_storage, + allow_send_messages, + allow_register_runners, + } => { + self.sandbox( + data, + allow_write_storage, + allow_send_messages, + allow_register_runners, + ) + .await + } gl_call::Message::RegisterRunner { code } => self.register_runner(code).await, gl_call::Message::Trace(message) => self.gl_call_trace(message).await, } @@ -1849,7 +1859,9 @@ impl ContextVFS<'_> { async fn sandbox( &mut self, data: bytes::Bytes, - allow_write_ops: bool, + allow_write_storage: bool, + allow_send_messages: bool, + allow_register_runners: bool, ) -> Result { let supervisor = self.context.data.supervisor.clone(); @@ -1880,11 +1892,11 @@ impl ContextVFS<'_> { needs_error_fingerprint: false, is_deterministic: zelf_conf.is_deterministic, can_read_storage: zelf_conf.can_read_storage, - can_write_storage: zelf_conf.can_write_storage & allow_write_ops, + can_write_storage: zelf_conf.can_write_storage & allow_write_storage, can_spawn_nondet: false, can_call_others: false, - can_send_messages: zelf_conf.can_send_messages & allow_write_ops, - can_register_runners: false, + can_send_messages: zelf_conf.can_send_messages & allow_send_messages, + can_register_runners: zelf_conf.can_register_runners & allow_register_runners, state_mode: zelf_conf.state_mode, }, message_data, diff --git a/runners/genlayer-py-std/src/genlayer/vm/__init__.py b/runners/genlayer-py-std/src/genlayer/vm/__init__.py index a5183379a..a0abc2173 100644 --- a/runners/genlayer-py-std/src/genlayer/vm/__init__.py +++ b/runners/genlayer-py-std/src/genlayer/vm/__init__.py @@ -158,7 +158,11 @@ def _decode_sub_vm_result( @_lazy_api def spawn_sandbox[T: calldata.Decoded]( - fn: typing.Callable[[], T], *, allow_write_ops: bool = False + fn: typing.Callable[[], T], + *, + allow_write_storage: bool = False, + allow_send_messages: bool = False, + allow_register_runners: bool = False, ) -> Lazy[Return[T] | VMError | UserError]: """ Runs a function in an isolated sandbox environment. @@ -167,8 +171,13 @@ def spawn_sandbox[T: calldata.Decoded]( This provides isolation and security for potentially unsafe operations. Determinism of spawned VM matches the determinism of the current VM. + Each ``allow_*`` flag grants the corresponding permission to the sandbox, but + only if the current VM holds it as well. + :param fn: Function to execute in the sandbox (must be serializable with cloudpickle) - :param allow_write_ops: Whether to allow write operations in the sandbox. Only effective if current VM has corresponding permission + :param allow_write_storage: Whether to allow storage writes in the sandbox + :param allow_send_messages: Whether to allow sending messages in the sandbox + :param allow_register_runners: Whether to allow registering runners in the sandbox Example: >>> result = spawn_sandbox(lambda: risky_computation()) @@ -180,7 +189,9 @@ def spawn_sandbox[T: calldata.Decoded]( { 'Sandbox': { 'data': cloudpickle.dumps(fn), - 'allow_write_ops': allow_write_ops, + 'allow_write_storage': allow_write_storage, + 'allow_send_messages': allow_send_messages, + 'allow_register_runners': allow_register_runners, } }, _decode_sub_vm_result_retn, @@ -287,7 +298,9 @@ def real_validator_fn(stage_data) -> bool: import genlayer.vm as vm answer = vm.spawn_sandbox( - lambda: validator_fn(leaders_result), allow_write_ops=True + lambda: validator_fn(leaders_result), + allow_write_storage=True, + allow_send_messages=True, ) if type(answer) is not type(leaders_result): diff --git a/tests/cases/stable/py/balances/sandbox_overspend.py b/tests/cases/stable/py/balances/sandbox_overspend.py index fbbf1d5f9..89dd460c7 100644 --- a/tests/cases/stable/py/balances/sandbox_overspend.py +++ b/tests/cases/stable/py/balances/sandbox_overspend.py @@ -12,7 +12,7 @@ def __init__(self): balance_after_first = self.balance print(f'balance before={balance_before} after_first_send={balance_after_first}') - # Now spawn a sandbox with write ops allowed. + # Now spawn a sandbox with message sending allowed. # BUG: the sandbox gets a fresh messages_decremented=0, # so it thinks the full balance is still available. def sandbox_fn(): @@ -22,7 +22,7 @@ def sandbox_fn(): gl.contract.get_at(target).emit_transfer(value=60) return self.balance - result = gl.vm.spawn_sandbox(sandbox_fn, allow_write_ops=True) + result = gl.vm.spawn_sandbox(sandbox_fn, allow_send_messages=True) print(f'sandbox result={result}') print(f'balance final={self.balance}') # If we reach here with both transfers accepted, diff --git a/tests/cases/stable/py/balances/sandbox_overspend_2.py b/tests/cases/stable/py/balances/sandbox_overspend_2.py index eaffe1504..620bf90c8 100644 --- a/tests/cases/stable/py/balances/sandbox_overspend_2.py +++ b/tests/cases/stable/py/balances/sandbox_overspend_2.py @@ -12,7 +12,7 @@ def sandbox_fn(): gl.contract.get_at(target).emit_transfer(value=60) return self.balance - result = gl.vm.spawn_sandbox(sandbox_fn, allow_write_ops=True) + result = gl.vm.spawn_sandbox(sandbox_fn, allow_send_messages=True) print(f'sandbox result={result} balance after sandbox={self.balance}') try: diff --git a/tests/cases/stable/py/sandbox/det/sandbox_write.py b/tests/cases/stable/py/sandbox/det/sandbox_write.py index 861985684..648e86986 100644 --- a/tests/cases/stable/py/sandbox/det/sandbox_write.py +++ b/tests/cases/stable/py/sandbox/det/sandbox_write.py @@ -13,5 +13,5 @@ def sb(): self.counter += 1 print(f'counter before: {self.counter}') - gl.vm.spawn_sandbox(sb, allow_write_ops=True) + gl.vm.spawn_sandbox(sb, allow_write_storage=True) print(f'counter after: {self.counter}') From 4c048cd67318c88df54340cc4a730ffd603771f4 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Fri, 19 Jun 2026 23:36:17 +0900 Subject: [PATCH 005/124] =?UTF-8?q?test(executor):=20cover=20malformed=20a?= =?UTF-8?q?nd=20missing=20custom=20runner=20ids=20=E2=9C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/cases/stable/runners/custom_malformed.0.stdout | 1 + tests/cases/stable/runners/custom_malformed.jsonnet | 3 +++ tests/cases/stable/runners/custom_malformed.py | 2 ++ tests/cases/stable/runners/custom_missing.0.stdout | 1 + tests/cases/stable/runners/custom_missing.jsonnet | 3 +++ tests/cases/stable/runners/custom_missing.py | 2 ++ 6 files changed, 12 insertions(+) create mode 100644 tests/cases/stable/runners/custom_malformed.0.stdout create mode 100644 tests/cases/stable/runners/custom_malformed.jsonnet create mode 100644 tests/cases/stable/runners/custom_malformed.py create mode 100644 tests/cases/stable/runners/custom_missing.0.stdout create mode 100644 tests/cases/stable/runners/custom_missing.jsonnet create mode 100644 tests/cases/stable/runners/custom_missing.py diff --git a/tests/cases/stable/runners/custom_malformed.0.stdout b/tests/cases/stable/runners/custom_malformed.0.stdout new file mode 100644 index 000000000..3a6b81bc5 --- /dev/null +++ b/tests/cases/stable/runners/custom_malformed.0.stdout @@ -0,0 +1 @@ +executed with `VMError("invalid_contract malformed_runner")` diff --git a/tests/cases/stable/runners/custom_malformed.jsonnet b/tests/cases/stable/runners/custom_malformed.jsonnet new file mode 100644 index 000000000..8df849cb4 --- /dev/null +++ b/tests/cases/stable/runners/custom_malformed.jsonnet @@ -0,0 +1,3 @@ +local simple = import 'templates/simple_deploy.jsonnet'; +local util = import 'templates/util.jsonnet'; +{entry: util.addPaths([simple.run('${jsonnetDir}/custom_malformed.py') {stable_hash: false}])} diff --git a/tests/cases/stable/runners/custom_malformed.py b/tests/cases/stable/runners/custom_malformed.py new file mode 100644 index 000000000..d2f8a99c8 --- /dev/null +++ b/tests/cases/stable/runners/custom_malformed.py @@ -0,0 +1,2 @@ +# { "Depends": "custom:" } +exit(0) diff --git a/tests/cases/stable/runners/custom_missing.0.stdout b/tests/cases/stable/runners/custom_missing.0.stdout new file mode 100644 index 000000000..226138fdd --- /dev/null +++ b/tests/cases/stable/runners/custom_missing.0.stdout @@ -0,0 +1 @@ +executed with `VMError("invalid_contract")` diff --git a/tests/cases/stable/runners/custom_missing.jsonnet b/tests/cases/stable/runners/custom_missing.jsonnet new file mode 100644 index 000000000..86e5116a2 --- /dev/null +++ b/tests/cases/stable/runners/custom_missing.jsonnet @@ -0,0 +1,3 @@ +local simple = import 'templates/simple_deploy.jsonnet'; +local util = import 'templates/util.jsonnet'; +{entry: util.addPaths([simple.run('${jsonnetDir}/custom_missing.py') {stable_hash: false}])} diff --git a/tests/cases/stable/runners/custom_missing.py b/tests/cases/stable/runners/custom_missing.py new file mode 100644 index 000000000..81091e26a --- /dev/null +++ b/tests/cases/stable/runners/custom_missing.py @@ -0,0 +1,2 @@ +# { "Depends": "custom:0123abcd" } +exit(0) From 4691daa88dbe681904fa197a57a31f04fcf5a582 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Fri, 19 Jun 2026 23:42:16 +0900 Subject: [PATCH 006/124] =?UTF-8?q?chore(claude):=20add=20branch-review=20?= =?UTF-8?q?agents=20and=20skill=20=F0=9F=A4=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/agents/reviewer-implementation.md | 62 ++++++++++++++++++++++ .claude/agents/reviewer-security.md | 57 ++++++++++++++++++++ .claude/agents/reviewer-spec.md | 63 +++++++++++++++++++++++ .claude/skills/branch-review/SKILL.md | 21 ++++---- 4 files changed, 193 insertions(+), 10 deletions(-) create mode 100644 .claude/agents/reviewer-implementation.md create mode 100644 .claude/agents/reviewer-security.md create mode 100644 .claude/agents/reviewer-spec.md diff --git a/.claude/agents/reviewer-implementation.md b/.claude/agents/reviewer-implementation.md new file mode 100644 index 000000000..8330178ba --- /dev/null +++ b/.claude/agents/reviewer-implementation.md @@ -0,0 +1,62 @@ +--- +name: reviewer-implementation +description: Reviews the implementation of a GenVM branch — code-vs-spec drift, code quality, AI slop, duplicated logic, useless comments, and doc completeness. Use as the "implementation" pass of a branch review. +tools: Bash, Read, Grep, Glob +model: opus +--- + +You are the **implementation** pass of a GenVM branch review. You read the code +and judge how it is built. Read-only: never edit code. + +## Baseline + +Diff against the active dev branch, not `main`: + +- Default to `v0.3-dev` (or the current `v0.x-dev`) — confirm with + `git branch -a | grep dev`; fall back to `main` only if none exists. +- State the base in one line; ignore commits already on it. +- `git log --oneline ..HEAD` / `git diff --stat ..HEAD`, then read the + diffs of the changed code. + +## What to report (with file:line evidence) + +1. **Code-vs-spec drift.** Verify the implementation matches the ADR/spec + claim-for-claim: every form/grammar/permission/limit the spec names exists in + code with the same semantics, and the code does not add user-visible behavior + the spec omits. Call out each divergence. + +2. **Doc / SDK completeness.** New `gl_call`s, permissions, runner-id forms, etc. + must be reflected in `doc/website/src/spec/**`, `doc/schemas/*.json`, and any + SDK wrappers/docstrings. Flag anything implemented but undocumented. + +3. **AI slop & duplicated logic.** Deliberate engineering or generated filler? + Flag over-abstraction, padded boilerplate, dead/duplicated parsers, copy-paste, + and clever-for-no-reason indirection. Say plainly when it is NOT slop. + Specifically: a new `gl_call` handler (e.g. `register_runner` in + `wasi/genlayer_sdk.rs` and `Supervisor` helpers) must **share the underlying + loading/resolution logic with the runner loader in + `executor/src/rt/supervisor/actions.rs`** rather than reimplementing archive + parsing, id canonicalization, or cache insertion. A second parallel code path + doing what the loader already does is a finding — name the function it should + route through. + +4. **Correctness & quality.** Panics on malformed input (`slice`, `unwrap`), + error handling, idempotency. + +5. **Edge cases are tested.** Enumerate the edge cases of each new surface and + verify each has a test: the happy path is not enough. Expect negative tests for + missing permission, non-deterministic mode, malformed / non-existing ids, and + stress/loop cases (e.g. registering the same thing ~1000× to prove + consume-once). Name each untested edge case as a gap. + +6. **Useless comments.** Flag narrate-the-obvious comments. Good comments explain + *why* (invariants, cache dedup, lifecycle) — credit those. + +Do NOT flag the dev-mode / `hashes=test` build state — intentional, not a finding. +Resource-accounting / consume-once limiter bugs are owned by the security +reviewer; mention only if it also reads as duplicated logic. + +## Style + +Concise and direct. Lead with: is the implementation correct and clean enough to +merge? Separate blocking issues from nits. Note if you did not build or run tests. diff --git a/.claude/agents/reviewer-security.md b/.claude/agents/reviewer-security.md new file mode 100644 index 000000000..11798cf71 --- /dev/null +++ b/.claude/agents/reviewer-security.md @@ -0,0 +1,57 @@ +--- +name: reviewer-security +description: Security review of a GenVM branch — attacker mindset over permissions, resource limits, sandbox propagation, parsing, and state-exfiltration. Use as the "security" pass of a branch review. +tools: Bash, Read, Grep, Glob +model: opus +--- + +You are the **security** pass of a GenVM branch review. Think like an attacker +writing a malicious contract. Read-only: never edit code. + +First read the repo root `SECURITY.md` — it is the source of truth for the threat +model, scope, and severity ladder. Rank every finding by the priority it defines +and cite that priority. Do not restate its contents in your report; reference it. + +## Baseline + +Diff against the active dev branch, not `main`: + +- Default to `v0.3-dev` (or the current `v0.x-dev`) — confirm with + `git branch -a | grep dev`; fall back to `main` only if none exists. +- State the base in one line; ignore commits already on it. +- `git log --oneline ..HEAD` / `git diff --stat ..HEAD`, then read the + diffs of the executor, wasi, supervisor, storage, and runner code. + +## What to check (with file:line evidence) + +- **Permission gates.** Every new capability is gated on its permission char AND + on `is_deterministic` where required. Check the gate is at entry, before any + side effect. +- **Permission propagation.** New capabilities are correctly disabled / inherited + in sub-VMs, the sandbox (`& allow_write_ops`), and nondet spawns — not silently + leaked into a more-privileged child. +- **Allocation bounded before allocating.** Reads/parses must charge the limiter + *before* allocating: decompression bombs (reject non-`Stored` zip entries), + length-prefixed reads, archive sizes. Charging after the alloc is a finding. +- **Resource accounting is consume-once.** A charge that scales with repeated + calls is a REAL BUG, not a conservative nit. Content-addressed resources (e.g. a + `custom:` runner) must be charged **once** — registering/loading the same + thing N times must not consume the limit N times. The test: "do it ~1000× in a + loop — does the limit overflow?" If yes, flag it and prescribe dedup-by-hash / + consume-once. Never excuse N-times charging as "errs safe." +- **Strict input parsing.** IDs/addresses/slots parsed with exact lengths and a + closed grammar; reserved prefixes truly reserved; malformed input rejected, not + coerced. +- **Read-oracle / exfiltration.** Does a new primitive let a contract read another + contract's state, or observe data it shouldn't? A blob that is loaded+executed + (not returned) is usually safe; a path that returns bytes to the caller is not. +- **Determinism.** New reads/branches in deterministic mode must be consensus-safe + (same result across validators). + +Do NOT flag the dev-mode / `hashes=test` build state — intentional, not a finding. + +## Style + +Concise. Lead with: any exploitable issue, yes/no, and what blocks merge. +Distinguish a real vuln from a hardening nice-to-have. Note if you did not build +or run anything. diff --git a/.claude/agents/reviewer-spec.md b/.claude/agents/reviewer-spec.md new file mode 100644 index 000000000..4fc4f4683 --- /dev/null +++ b/.claude/agents/reviewer-spec.md @@ -0,0 +1,63 @@ +--- +name: reviewer-spec +description: Reviews the ADR/proposal and spec/schema of a GenVM branch as documents — soundness, clarity, and completeness (what was forgotten). Use as the "spec" pass of a branch review. +tools: Bash, Read, Grep, Glob +model: opus +--- + +You review the **specification** of a GenVM branch — the ADR, the spec/docs, the +schemas — as documents: is the proposal sound, clear, and self-consistent? You do +NOT cross-check the implementation (whether the code matches the spec is the +implementation reviewer's job). Read-only: never edit code. + +## Baseline + +Diff against the active dev branch, not `main`: + +- Default to `v0.3-dev` (or the current `v0.x-dev`) — confirm with + `git branch -a | grep dev`; fall back to `main` only if none exists. +- State the base in one line at the top; ignore commits already on it. +- `git log --oneline ..HEAD` and `git diff --stat ..HEAD`, then read + the diffs of `doc/**` and `*.json` schemas. + +## What to report + +With file:line evidence: + +1. **ADR / proposal quality.** If the branch adds or changes a `doc/adr/*.md` + (or design doc), rate it. Good = concrete context with real linked issues, a + precise decision (grammar/types/IDs spelled out unambiguously), honest + consequences including breaking changes and footguns, and genuine + alternatives-considered. If there's no ADR for a change that warrants one, + say so. + +2. **Spec / schema soundness.** Read the spec and schema changes as a contract a + third party would implement against: is every form/grammar/permission/limit + defined precisely and unambiguously? Are there gaps, contradictions, or + under-specified edges? Is the JSON schema itself valid and matching the prose? + This is about the spec being *correct and complete on its own terms* — not + about the code. + +3. **Completeness — what did we forget to add?** A change usually touches a whole + family of surfaces; flag any the proposal/spec missed. E.g. a new `gl_call` + typically needs: a spec page, a JSON-schema entry, a permission (with its char + documented in the permissions spec), an SDK wrapper, error/edge-case + documentation, and a migration/breaking-change note if it changes existing + behavior. A new id/grammar form needs its schema pattern plus mention anywhere + the old forms are enumerated. List the surfaces that *should* have changed + together but didn't. + +4. **Edge cases are documented or inferrable.** Enumerate the edge cases of each + new surface (malformed input, missing permission, non-deterministic mode, + not-found / collision, limits hit) and check the spec either states the + behavior or makes it unambiguously inferrable from the stated rules. A behavior + a reader would have to guess is a spec gap — list each one. (Whether those + edge cases are *tested* is the implementation reviewer's job.) + +Do NOT flag the dev-mode / `hashes=test` build state — it is intentional (known +flag to ignore test hashes), not a finding. + +## Style + +Concise and direct. Lead with: is the proposal sound and the spec implementable +as written? Separate blocking gaps from nits. Don't pad. diff --git a/.claude/skills/branch-review/SKILL.md b/.claude/skills/branch-review/SKILL.md index 9561a21dc..78fa08f8f 100644 --- a/.claude/skills/branch-review/SKILL.md +++ b/.claude/skills/branch-review/SKILL.md @@ -5,15 +5,15 @@ description: Reviews the current GenVM branch by fanning out three specialized r # Reviewing a GenVM branch -Run a three-pass review using the dedicated subagents. Launch all three **in a -single message** (one Agent tool call each) so they run concurrently — they are -independent and read-only. +Run a three-pass review using the dedicated subagents. The spec pass runs +**first** as a gate; the security and implementation passes run **concurrently** +after it (both in a single message). All three are read-only. | Pass | Agent (`subagent_type`) | Owns | | --- | --- | --- | -| Spec | `spec-reviewer` | ADR/proposal quality; spec & schema soundness as documents | -| Security | `security-reviewer` | permissions, sandbox propagation, limiter/consume-once, parsing, exfiltration | -| Implementation | `implementation-reviewer` | code-vs-spec drift, AI slop, duplicated logic, doc completeness, useless comments | +| Spec | `reviewer-spec` | ADR/proposal quality; spec & schema soundness; completeness; edge cases documented/inferrable | +| Security | `reviewer-security` | permissions, sandbox propagation, limiter/consume-once, parsing, exfiltration (ranked by `SECURITY.md`) | +| Implementation | `reviewer-implementation` | code-vs-spec drift, AI slop, duplicated logic, edge cases tested, doc completeness, useless comments | ## Baseline @@ -25,10 +25,11 @@ finding — it is intentional. ## Procedure 1. Confirm the base branch (default `v0.3-dev`). -2. In one message, spawn `spec-reviewer`, `security-reviewer`, and - `implementation-reviewer`, each told the base branch and any extra scope the - user gave. -3. Synthesize their three reports into one review: lead with the merge verdict, +2. Spawn `reviewer-spec`, told the base branch and any extra scope the user gave. + After it finishes, if it found issues discuss with the user before proceeding. +3. In one message, spawn `reviewer-security` and `reviewer-implementation`, each + told the base branch and any extra scope the user gave. +4. Synthesize their three reports into one review: lead with the merge verdict, then a **Blocking** section and a **Nits** section, attributing findings to their pass. De-duplicate overlaps (e.g. a duplicated-logic issue both security and implementation raise) into a single entry. From de276c26f7cb4a6b59740a67acdef7ecde0026c6 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Fri, 19 Jun 2026 23:52:12 +0900 Subject: [PATCH 007/124] =?UTF-8?q?feat(wasi):=20add=20MapFile=20gl=5Fcall?= =?UTF-8?q?=20to=20map=20runner=20files=20at=20runtime=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../03-wasi_genlayer_sdk/02-gl_call.rst | 20 + executor/crates/sdk-rs/src/abi/gl_call.rs | 6 + executor/src/rt/supervisor/actions.rs | 477 +++++++++--------- executor/src/rt/supervisor/mod.rs | 2 +- executor/src/runners/mod.rs | 7 + executor/src/wasi/genlayer_sdk.rs | 45 ++ executor/src/wasi/mod.rs | 1 + .../src/genlayer/vm/__init__.py | 25 + .../stable/runners/map_runner_file.0.stdout | 2 + .../stable/runners/map_runner_file.jsonnet | 3 + tests/cases/stable/runners/map_runner_file.py | 9 + 11 files changed, 370 insertions(+), 227 deletions(-) create mode 100644 tests/cases/stable/runners/map_runner_file.0.stdout create mode 100644 tests/cases/stable/runners/map_runner_file.jsonnet create mode 100644 tests/cases/stable/runners/map_runner_file.py diff --git a/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst b/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst index e8bf453d5..db96e67a3 100644 --- a/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst +++ b/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst @@ -213,6 +213,26 @@ Requirements #. :ref:`gvm-perm-deterministic` #. :ref:`gvm-perm-register-runners` +``MapFile`` Message +------------------- + +Maps a file from a runner into the VM filesystem at runtime, behaving the same as +the ``MapFile`` runner action (see :doc:`../../../python-sdk` runners). If +``path_in_runner`` ends with ``/`` the whole directory subtree is mapped. + +Payload +~~~~~~~ + +.. code-block:: + + { + "MapFile": { + "runner": String, // runner id (name:hash, contract, chain:..., custom:...) + "path_in_runner": String, // path within the runner archive + "path_in_vfs": String // absolute destination path in the VM filesystem + } + } + ``WebRender`` Message --------------------- diff --git a/executor/crates/sdk-rs/src/abi/gl_call.rs b/executor/crates/sdk-rs/src/abi/gl_call.rs index cb0960444..99f121360 100644 --- a/executor/crates/sdk-rs/src/abi/gl_call.rs +++ b/executor/crates/sdk-rs/src/abi/gl_call.rs @@ -583,6 +583,12 @@ pub enum Message { code: Bytes, }, + MapFile { + runner: String, + path_in_runner: String, + path_in_vfs: String, + }, + WebRender(web_iface::RenderPayload), WebRequest(web_iface::RequestPayload), ExecPrompt(llm_iface::PromptPayload), diff --git a/executor/src/rt/supervisor/actions.rs b/executor/src/rt/supervisor/actions.rs index fc33303cf..06afc93ff 100644 --- a/executor/src/rt/supervisor/actions.rs +++ b/executor/src/rt/supervisor/actions.rs @@ -54,67 +54,253 @@ struct Resolved { kind: ResolvedKind, } -impl Ctx<'_, '_> { - fn resolve_runner(&self, id: symbol_table::GlobalSymbol) -> anyhow::Result { - let Some(parsed) = runners::parse_runner_id(id.as_str()) else { - return Err(make_malformed_runner_error( - "runner id doesn't match expected format", - )); - }; +/// Resolves a runner id to its canonical cache key and load strategy. +/// +/// Free-standing so it can be shared between contract initialization +/// ([`Ctx`]) and runtime `gl_call`s ([`load_runner`]). +fn resolve_runner( + supervisor: &rt::supervisor::Supervisor, + contract_id: symbol_table::GlobalSymbol, + id: symbol_table::GlobalSymbol, +) -> anyhow::Result { + let Some(parsed) = runners::parse_runner_id(id.as_str()) else { + return Err(make_malformed_runner_error( + "runner id doesn't match expected format", + )); + }; + + match parsed { + runners::RunnerId::Contract => Ok(Resolved { + id: contract_id, + kind: ResolvedKind::Preloaded, + }), + runners::RunnerId::NameHash { name, hash } => { + let hash = if hash.as_str() == "test" || hash.as_str() == "latest" { + if !supervisor.shared_data.debug_mode { + log_warn!(":test/ :latest runner used in non-debug mode, this is not allowed"); + return Err(make_malformed_runner_error( + "runner id doesn't match expected format", + )); + } + let new_latest = supervisor.runner_cache.get_latest(name); + log_info!(runner_id = name.as_str(), new_latest:? = new_latest; "resolving :latest runner"); + let Some(new_latest) = new_latest else { + return Err(make_malformed_runner_error( + "runner id doesn't match expected format", + )); + }; + new_latest + } else { + hash + }; - match parsed { - runners::RunnerId::Contract => Ok(Resolved { - id: self.contract_id, - kind: ResolvedKind::Preloaded, - }), - runners::RunnerId::NameHash { name, hash } => { - let hash = if hash.as_str() == "test" || hash.as_str() == "latest" { - if !self.supervisor.shared_data.debug_mode { - log_warn!( - ":test/ :latest runner used in non-debug mode, this is not allowed" + if !supervisor.runner_cache.has_in_all(name, hash) { + anyhow::bail!("runner {}:{} not found", name, hash); + } + + let mut canonical = name.as_str().to_owned(); + canonical.push(':'); + canonical.push_str(hash.as_str()); + + Ok(Resolved { + id: GlobalSymbol::new(canonical), + kind: ResolvedKind::Disk { name, hash }, + }) + } + runners::RunnerId::Chain { address, on, slot } => Ok(Resolved { + id: GlobalSymbol::from(runners::chain_canonical(address, on, slot)), + kind: ResolvedKind::Chain { address, on, slot }, + }), + runners::RunnerId::Custom { hash } => Ok(Resolved { + id: runners::custom_runner_id(hash), + kind: ResolvedKind::Custom { hash }, + }), + } +} + +/// Loads (and caches) the archive for an already-resolved runner. +async fn get_arch( + supervisor: &rt::supervisor::Supervisor, + limiter: &rt::memlimiter::Limiter, + resolved: Resolved, +) -> anyhow::Result<( + symbol_table::GlobalSymbol, + sync::DArc, +)> { + let Resolved { id, kind } = resolved; + + let cache = &supervisor.runner_cache; + + let new_arch = match kind { + ResolvedKind::Disk { name, hash } => { + cache + .get_or_create( + id, + || async { + let mut path = cache.runners_path().to_owned(); + runners::append_runner_subpath(name.as_str(), hash.as_str(), &mut path); + path.set_extension("tar"); + if !path.exists() { + anyhow::bail!("runner {} not found", id); + } + + let data = util::mmap_file(&path) + .with_context(|| format!("memory mapping runner archive for {id}"))?; + let data = bytes::Bytes::copy_from_slice(data.as_ref()); + runners::Archive::from_ustar(data) + .with_context(|| format!("parsing ustar archive for {id}")) + }, + limiter, + ) + .await? + } + ResolvedKind::Preloaded => { + cache + .get_or_create( + id, + || async { anyhow::bail!("runner {} is not preloaded", id) }, + limiter, + ) + .await? + } + ResolvedKind::Chain { address, on, slot } => { + cache + .get_or_create( + id, + || async { + let mut storage = rt::vm::storage::Storage::new( + address, + supervisor.get_storage_limiter(), + crate::wasi::genlayer_sdk::StorageHostHolder( + supervisor.host.clone(), + crate::wasi::genlayer_sdk::ReadToken { + account: address, + mode: on, + }, + ), ); - return Err(make_malformed_runner_error( - "runner id doesn't match expected format", - )); - } - let new_latest = self.supervisor.runner_cache.get_latest(name); - log_info!(runner_id = name.as_str(), new_latest:? = new_latest; "resolving :latest runner"); - let Some(new_latest) = new_latest else { - return Err(make_malformed_runner_error( - "runner id doesn't match expected format", - )); - }; - new_latest - } else { - hash - }; + let code = storage + .read_code_at(slot, limiter) + .await + .with_context(|| format!("reading chain runner code for {id}"))?; + runners::parse(bytes::Bytes::from(code)) + .with_context(|| format!("parsing chain runner for {id}")) + }, + limiter, + ) + .await? + } + ResolvedKind::Custom { hash } => { + cache + .get_or_create( + id, + || async { + supervisor + .get_custom_runner(hash) + .ok_or_else(|| anyhow::anyhow!("custom runner {} not found", id)) + }, + limiter, + ) + .await? + } + }; - if !self.supervisor.runner_cache.has_in_all(name, hash) { - anyhow::bail!("runner {}:{} not found", name, hash); - } + Ok((id, new_arch)) +} + +/// Resolves and loads a runner archive by id. Shared entry point used by both +/// contract initialization and runtime `gl_call`s. +pub(crate) async fn load_runner( + supervisor: &rt::supervisor::Supervisor, + contract_id: symbol_table::GlobalSymbol, + limiter: &rt::memlimiter::Limiter, + id: symbol_table::GlobalSymbol, +) -> anyhow::Result<( + symbol_table::GlobalSymbol, + sync::DArc, +)> { + let resolved = resolve_runner(supervisor, contract_id, id)?; + get_arch(supervisor, limiter, resolved).await +} + +/// Maps a file (or, when `file` ends with `/`, a directory subtree) from a +/// runner archive into the VM filesystem at `to`. Mirrors [`InitAction::MapFile`] +/// so the runtime `MapFile` `gl_call` behaves identically. +pub(crate) fn map_archive_file( + preview1: &mut crate::wasi::preview1::Context, + limiter: &rt::memlimiter::Limiter, + cancellation: &genvm_common::cancellation::Token, + arch: &runners::ArchiveCache, + file: &str, + to: &str, +) -> anyhow::Result<()> { + if file.ends_with("/") { + let is_root = file == "/"; + + let range = if is_root { + arch.files.data.range::(..) + } else { + arch.files.data.range(String::from(file)..) + }; + + let must_start_with: &str = if is_root { "" } else { file }; + + for (name, file_contents) in range { + if cancellation.is_cancelled() { + return Err(rt::errors::VMError(public_abi::VmError::timeout(), None).into()); + } + + if name.ends_with("/") { + continue; + } + + if !name.starts_with(must_start_with) { + log_trace!(from = file, to = to, name = name; "aborting file mapping"); + break; + } - let mut canonical = name.as_str().to_owned(); - canonical.push(':'); - canonical.push_str(hash.as_str()); + let mut name_in_fs = String::from(to); + if !name_in_fs.ends_with("/") { + name_in_fs.push('/'); + } + name_in_fs.push_str(&name[must_start_with.len()..]); - Ok(Resolved { - id: GlobalSymbol::new(canonical), - kind: ResolvedKind::Disk { name, hash }, - }) + if maps_into_vm(&name_in_fs) { + return Err(make_malformed_runner_error(&format!( + "mapping into /vm/ is forbidden: {name_in_fs}" + ))); } - runners::RunnerId::Chain { address, on, slot } => Ok(Resolved { - id: GlobalSymbol::from(runners::chain_canonical(address, on, slot)), - kind: ResolvedKind::Chain { address, on, slot }, - }), - runners::RunnerId::Custom { hash } => { - let mut canonical = String::from("custom:"); - canonical.push_str(hash.as_str()); - Ok(Resolved { - id: GlobalSymbol::from(canonical), - kind: ResolvedKind::Custom { hash }, - }) + + if !limiter + .consume(public_abi::memory_limiter_consts::FILE_MAPPING + name_in_fs.len() as u32) + { + return Err( + rt::errors::VMError(abi::consts::VmError::oom().ram().val(), None).into(), + ); } + + preview1.map_file(&name_in_fs, file_contents.clone())?; } + } else { + if maps_into_vm(to) { + return Err(make_malformed_runner_error(&format!( + "mapping into /vm/ is forbidden: {to}" + ))); + } + + if !limiter.consume(public_abi::memory_limiter_consts::FILE_MAPPING + to.len() as u32) { + return Err(rt::errors::VMError(abi::consts::VmError::oom().ram().val(), None).into()); + } + + preview1.map_file(to, arch.get_file(file)?)?; + } + + Ok(()) +} + +impl Ctx<'_, '_> { + fn resolve_runner(&self, id: symbol_table::GlobalSymbol) -> anyhow::Result { + resolve_runner(self.supervisor, self.contract_id, id) } async fn get_arch( @@ -124,89 +310,8 @@ impl Ctx<'_, '_> { symbol_table::GlobalSymbol, sync::DArc, )> { - let Resolved { id, kind } = resolved; - let limiter = self.vm.store.data_mut().limits.clone(); - let cache = &self.supervisor.runner_cache; - - let new_arch = match kind { - ResolvedKind::Disk { name, hash } => { - cache - .get_or_create( - id, - || async { - let mut path = cache.runners_path().to_owned(); - runners::append_runner_subpath(name.as_str(), hash.as_str(), &mut path); - path.set_extension("tar"); - if !path.exists() { - anyhow::bail!("runner {} not found", id); - } - - let data = util::mmap_file(&path).with_context(|| { - format!("memory mapping runner archive for {id}") - })?; - let data = bytes::Bytes::copy_from_slice(data.as_ref()); - runners::Archive::from_ustar(data) - .with_context(|| format!("parsing ustar archive for {id}")) - }, - &limiter, - ) - .await? - } - ResolvedKind::Preloaded => { - cache - .get_or_create( - id, - || async { anyhow::bail!("runner {} is not preloaded", id) }, - &limiter, - ) - .await? - } - ResolvedKind::Chain { address, on, slot } => { - let supervisor = self.supervisor; - cache - .get_or_create( - id, - || async { - let mut storage = rt::vm::storage::Storage::new( - address, - supervisor.get_storage_limiter(), - crate::wasi::genlayer_sdk::StorageHostHolder( - supervisor.host.clone(), - crate::wasi::genlayer_sdk::ReadToken { - account: address, - mode: on, - }, - ), - ); - let code = storage - .read_code_at(slot, &limiter) - .await - .with_context(|| format!("reading chain runner code for {id}"))?; - runners::parse(bytes::Bytes::from(code)) - .with_context(|| format!("parsing chain runner for {id}")) - }, - &limiter, - ) - .await? - } - ResolvedKind::Custom { hash } => { - let supervisor = self.supervisor; - cache - .get_or_create( - id, - || async { - supervisor - .get_custom_runner(hash) - .ok_or_else(|| anyhow::anyhow!("custom runner {} not found", id)) - }, - &limiter, - ) - .await? - } - }; - - Ok((id, new_arch)) + get_arch(self.supervisor, &limiter, resolved).await } fn load_modules( @@ -309,97 +414,17 @@ impl Ctx<'_, '_> { match action { InitAction::MapFile { to, file } => { - if file.ends_with("/") { - let is_root = file.as_ref() == "/"; - - let file_name_str = String::from(&file[..]); - - let range = if is_root { - current_runner_arch - .files - .data - .range::(..) - } else { - current_runner_arch.files.data.range(file_name_str..) - }; - - let must_start_with: &str = if is_root { "" } else { file.as_ref() }; - - for (name, file_contents) in range { - if self.supervisor.shared_data.cancellation.is_cancelled() { - return Err( - rt::errors::VMError(public_abi::VmError::timeout(), None).into() - ); - } - - if name.ends_with("/") { - continue; - } - - if !name.starts_with(must_start_with) { - log_trace!(from = file, to = to, name = name; "aborting file mapping"); - - break; - } - - let mut name_in_fs = String::from(&to[..]); - if !name_in_fs.ends_with("/") { - name_in_fs.push('/'); - } - name_in_fs.push_str(&name[must_start_with.len()..]); - - if maps_into_vm(&name_in_fs) { - return Err(make_malformed_runner_error(&format!( - "mapping into /vm/ is forbidden: {name_in_fs}" - ))); - } - - let limiter = &self.vm.store.data_mut().limits; - - if !limiter.consume( - public_abi::memory_limiter_consts::FILE_MAPPING - + name_in_fs.len() as u32, - ) { - return Err(rt::errors::VMError( - abi::consts::VmError::oom().ram().val(), - None, - ) - .into()); - } - - self.vm - .store - .data_mut() - .genlayer_ctx_mut() - .preview1 - .map_file(&name_in_fs, file_contents.clone())?; - } - } else { - if maps_into_vm(to) { - return Err(make_malformed_runner_error(&format!( - "mapping into /vm/ is forbidden: {to}" - ))); - } - - let limiter = &self.vm.store.data_mut().limits; - - if !limiter - .consume(public_abi::memory_limiter_consts::FILE_MAPPING + to.len() as u32) - { - return Err(rt::errors::VMError( - abi::consts::VmError::oom().ram().val(), - None, - ) - .into()); - } - - self.vm - .store - .data_mut() - .genlayer_ctx_mut() - .preview1 - .map_file(to, current_runner_arch.get_file(file)?)?; - } + let limiter = self.vm.store.data_mut().limits.clone(); + let cancellation = self.supervisor.shared_data.cancellation.clone(); + let preview1 = &mut self.vm.store.data_mut().genlayer_ctx_mut().preview1; + map_archive_file( + preview1, + &limiter, + &cancellation, + current_runner_arch, + file, + to, + )?; Ok(None) } InitAction::AddEnv { name, val } => { diff --git a/executor/src/rt/supervisor/mod.rs b/executor/src/rt/supervisor/mod.rs index f2a7b818a..64d66e3bc 100644 --- a/executor/src/rt/supervisor/mod.rs +++ b/executor/src/rt/supervisor/mod.rs @@ -13,7 +13,7 @@ use crate::{ runners, wasi, }; -mod actions; +pub(crate) mod actions; mod compilation; struct WasmModuleCache { diff --git a/executor/src/runners/mod.rs b/executor/src/runners/mod.rs index 242a514e2..02065f0aa 100644 --- a/executor/src/runners/mod.rs +++ b/executor/src/runners/mod.rs @@ -144,6 +144,13 @@ pub fn custom_runner_hash(code: &[u8]) -> symbol_table::GlobalSymbol { symbol_table::GlobalSymbol::from(hex::encode(digest.finalize())) } +/// Builds the canonical `custom:` runner id from its hash. +pub fn custom_runner_id(hash: symbol_table::GlobalSymbol) -> symbol_table::GlobalSymbol { + let mut id = String::from("custom:"); + id.push_str(hash.as_str()); + symbol_table::GlobalSymbol::from(id) +} + pub fn get_runner_of_contract( address: calldata::Address, state: crate::public_abi::StorageType, diff --git a/executor/src/wasi/genlayer_sdk.rs b/executor/src/wasi/genlayer_sdk.rs index 2e7e71da9..c9e3e3545 100644 --- a/executor/src/wasi/genlayer_sdk.rs +++ b/executor/src/wasi/genlayer_sdk.rs @@ -271,6 +271,7 @@ pub struct Context { pub struct ContextVFS<'a> { pub(super) vfs: &'a mut vfs::VFS, + pub(super) preview1: &'a mut super::preview1::Context, pub(super) context: &'a mut Context, } @@ -1356,6 +1357,11 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { .await } gl_call::Message::RegisterRunner { code } => self.register_runner(code).await, + gl_call::Message::MapFile { + runner, + path_in_runner, + path_in_vfs, + } => self.map_file(runner, path_in_runner, path_in_vfs).await, gl_call::Message::Trace(message) => self.gl_call_trace(message).await, } } @@ -1639,6 +1645,45 @@ impl ContextVFS<'_> { )) } + async fn map_file( + &mut self, + runner: String, + path_in_runner: String, + path_in_vfs: String, + ) -> Result { + let supervisor = self.context.data.supervisor.clone(); + let is_det = self.context.data.conf.is_deterministic; + let limiter = supervisor.limiter.get(is_det); + + let contract_address = self.context.data.message_data.message.contract_address; + let contract_id = crate::runners::get_runner_of_contract( + contract_address, + self.context.data.conf.state_mode, + ); + + let (_id, arch) = crate::rt::supervisor::actions::load_runner( + &supervisor, + contract_id, + limiter, + symbol_table::GlobalSymbol::from(runner), + ) + .await + .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?; + + let cancellation = supervisor.shared_data.cancellation.clone(); + crate::rt::supervisor::actions::map_archive_file( + self.preview1, + limiter, + &cancellation, + &arch, + &path_in_runner, + &path_in_vfs, + ) + .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?; + + Ok(file_fd_none()) + } + async fn run_nondet( &mut self, data_leader: bytes::Bytes, diff --git a/executor/src/wasi/mod.rs b/executor/src/wasi/mod.rs index ef5a2141d..ff5338f1e 100644 --- a/executor/src/wasi/mod.rs +++ b/executor/src/wasi/mod.rs @@ -153,6 +153,7 @@ pub(super) fn add_to_linker_sync( let r = self.0(arg); genlayer_sdk::ContextVFS { vfs: &mut r.vfs, + preview1: &mut r.preview1, context: &mut r.genlayer_sdk, } } diff --git a/runners/genlayer-py-std/src/genlayer/vm/__init__.py b/runners/genlayer-py-std/src/genlayer/vm/__init__.py index a0abc2173..64b656410 100644 --- a/runners/genlayer-py-std/src/genlayer/vm/__init__.py +++ b/runners/genlayer-py-std/src/genlayer/vm/__init__.py @@ -21,6 +21,7 @@ 'trace', 'trace_time_micro', 'register_runner', + 'map_file', 'ABI', ) @@ -368,3 +369,27 @@ def register_runner(code: collections.abc.Buffer) -> str: }, lambda x: typing.cast(str, calldata.decode(x)), ).get() + + +def map_file(runner: str, path_in_runner: str, path_in_vfs: str) -> None: + """ + Maps a file from a runner into the VM filesystem at runtime. + + Behaves the same as the ``MapFile`` runner action: if ``path_in_runner`` ends + with ``/`` the whole directory subtree is mapped, otherwise a single file. + + :param runner: runner id (e.g. ``name:hash``, ``contract``, ``custom:``) + :param path_in_runner: path within the runner archive + :param path_in_vfs: absolute destination path in the VM filesystem + """ + wasi.gl_call( + calldata.encode( + { + 'MapFile': { + 'runner': runner, + 'path_in_runner': path_in_runner, + 'path_in_vfs': path_in_vfs, + } + } + ) + ) diff --git a/tests/cases/stable/runners/map_runner_file.0.stdout b/tests/cases/stable/runners/map_runner_file.0.stdout new file mode 100644 index 000000000..ad485fd94 --- /dev/null +++ b/tests/cases/stable/runners/map_runner_file.0.stdout @@ -0,0 +1,2 @@ +True +executed with `Return(null)` diff --git a/tests/cases/stable/runners/map_runner_file.jsonnet b/tests/cases/stable/runners/map_runner_file.jsonnet new file mode 100644 index 000000000..fe80f8019 --- /dev/null +++ b/tests/cases/stable/runners/map_runner_file.jsonnet @@ -0,0 +1,3 @@ +local simple = import 'templates/simple_deploy.jsonnet'; +local util = import 'templates/util.jsonnet'; +{entry: util.addPaths([simple.run('${jsonnetDir}/map_runner_file.py') {stable_hash: false}])} diff --git a/tests/cases/stable/runners/map_runner_file.py b/tests/cases/stable/runners/map_runner_file.py new file mode 100644 index 000000000..aaeb14000 --- /dev/null +++ b/tests/cases/stable/runners/map_runner_file.py @@ -0,0 +1,9 @@ +# { "Depends": "py-genlayer:test" } +from genlayer.vm import register_runner, map_file + +code = b'# { "Depends": "py-genlayer:test" }\nmarker-12345\n' +rid = register_runner(code) +map_file(rid, 'file', '/mapped.txt') +with open('/mapped.txt', 'rb') as f: + print(f.read() == code) +exit(0) From e68cee0848176f530b5e3d5e6ab47fefcac3fc7c Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Sat, 20 Jun 2026 00:30:19 +0900 Subject: [PATCH 008/124] =?UTF-8?q?fix(executor):=20charge=20custom=20runn?= =?UTF-8?q?er=20memory=20once=20per=20registration=20=F0=9F=90=9B=E2=99=BB?= =?UTF-8?q?=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/src/rt/supervisor/mod.rs | 69 ++++++++++++++++--- executor/src/wasi/genlayer_sdk.rs | 27 ++------ .../stable/runners/register_loop.0.stdout | 2 + .../stable/runners/register_loop.jsonnet | 3 + tests/cases/stable/runners/register_loop.py | 12 ++++ 5 files changed, 81 insertions(+), 32 deletions(-) create mode 100644 tests/cases/stable/runners/register_loop.0.stdout create mode 100644 tests/cases/stable/runners/register_loop.jsonnet create mode 100644 tests/cases/stable/runners/register_loop.py diff --git a/executor/src/rt/supervisor/mod.rs b/executor/src/rt/supervisor/mod.rs index 64d66e3bc..43648374b 100644 --- a/executor/src/rt/supervisor/mod.rs +++ b/executor/src/rt/supervisor/mod.rs @@ -229,17 +229,18 @@ impl Supervisor { self.custom_runners.get(&hash).map(|r| r.clone()) } - /// Registers a runner archive under `custom:`. Returns the canonical - /// runner id it can be referenced by. + /// Registers a runner from its `code`, returning the `custom:` id it can + /// be referenced by. + /// + /// The archive is parsed and charged against `limiter` only the first time a + /// given hash is seen — re-registering the same code is a cheap no-op, so a + /// contract cannot exhaust the memory limit by registering in a loop. pub fn register_custom_runner( &self, - hash: GlobalSymbol, - archive: runners::Archive, - ) -> GlobalSymbol { - self.custom_runners.insert(hash, archive); - let mut id = String::from("custom:"); - id.push_str(hash.as_str()); - GlobalSymbol::from(id) + code: bytes::Bytes, + limiter: &rt::memlimiter::Limiter, + ) -> anyhow::Result { + register_custom_runner_into(&self.custom_runners, code, limiter) } pub fn start(config: &config::Config, ctor: Ctor) -> anyhow::Result> { @@ -591,3 +592,53 @@ async fn nondet_vm_processor( std::mem::drop(read_permit); log_debug!(count = count; "nondet worker done"); } + +/// Core of [`Supervisor::register_custom_runner`]; charges the parsed archive +/// against `limiter` only on the first registration of a given hash. +fn register_custom_runner_into( + custom_runners: &dashmap::DashMap, + code: bytes::Bytes, + limiter: &rt::memlimiter::Limiter, +) -> anyhow::Result { + let hash = runners::custom_runner_hash(&code); + + if let dashmap::mapref::entry::Entry::Vacant(slot) = custom_runners.entry(hash) { + let archive = runners::parse(code).map_err(|e| { + rt::errors::VMError::wrap(public_abi::VmError::invalid_contract().val(), e) + })?; + if !limiter.consume(archive.total_size) { + return Err(rt::errors::VMError(public_abi::VmError::oom().ram().val(), None).into()); + } + slot.insert(archive); + } + + Ok(runners::custom_runner_id(hash)) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn register_custom_runner_consumes_once() { + let map = dashmap::DashMap::new(); + let limiter = rt::memlimiter::Limiter::new("test-register"); + let code = bytes::Bytes::from_static(b"# { \"Depends\": \"py-genlayer:test\" }\n"); + + let id = register_custom_runner_into(&map, code.clone(), &limiter).unwrap(); + let remaining_after_first = limiter.get_remaining_memory(); + + // the first registration must have charged the archive + assert!(remaining_after_first < u32::MAX); + + // re-registering the same code must be a cheap no-op: same id, no extra + // memory charged and no duplicate map entries + for _ in 0..1000 { + let again = register_custom_runner_into(&map, code.clone(), &limiter).unwrap(); + assert_eq!(again, id); + } + + assert_eq!(limiter.get_remaining_memory(), remaining_after_first); + assert_eq!(map.len(), 1); + } +} diff --git a/executor/src/wasi/genlayer_sdk.rs b/executor/src/wasi/genlayer_sdk.rs index c9e3e3545..a87ab6959 100644 --- a/executor/src/wasi/genlayer_sdk.rs +++ b/executor/src/wasi/genlayer_sdk.rs @@ -1608,30 +1608,11 @@ impl ContextVFS<'_> { return Err(generated::types::Errno::Forbidden.into()); } - let hash = crate::runners::custom_runner_hash(&code); - - let archive = crate::runners::parse(code) - .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?; - let is_det = self.context.data.conf.is_deterministic; - if !self - .context - .data - .supervisor - .limiter - .get(is_det) - .consume(archive.total_size) - { - return Err(generated::types::Error::trap(crate::anyhow_to_wasmtime( - rt::errors::VMError(abi::consts::VmError::oom().ram().val(), None).into(), - ))); - } - - let id = self - .context - .data - .supervisor - .register_custom_runner(hash, archive); + let supervisor = self.context.data.supervisor.clone(); + let id = supervisor + .register_custom_runner(code, supervisor.limiter.get(is_det)) + .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?; let data = calldata::encode(&calldata::Value::Str(id.as_str().to_owned())); Ok(generated::types::Fd::from( diff --git a/tests/cases/stable/runners/register_loop.0.stdout b/tests/cases/stable/runners/register_loop.0.stdout new file mode 100644 index 000000000..91d09e7d5 --- /dev/null +++ b/tests/cases/stable/runners/register_loop.0.stdout @@ -0,0 +1,2 @@ +custom:12cf083cef24fc898fdae3fada0792f6efe309557ac1ea02ec15ea58f136afa4 +executed with `Return(null)` diff --git a/tests/cases/stable/runners/register_loop.jsonnet b/tests/cases/stable/runners/register_loop.jsonnet new file mode 100644 index 000000000..d2109338a --- /dev/null +++ b/tests/cases/stable/runners/register_loop.jsonnet @@ -0,0 +1,3 @@ +local simple = import 'templates/simple_deploy.jsonnet'; +local util = import 'templates/util.jsonnet'; +{entry: util.addPaths([simple.run('${jsonnetDir}/register_loop.py') {stable_hash: false}])} diff --git a/tests/cases/stable/runners/register_loop.py b/tests/cases/stable/runners/register_loop.py new file mode 100644 index 000000000..5f3b43666 --- /dev/null +++ b/tests/cases/stable/runners/register_loop.py @@ -0,0 +1,12 @@ +# { "Depends": "py-genlayer:test" } +from genlayer.vm import register_runner + +# Registering the same runner repeatedly must be idempotent: it returns the same +# id every time and (see the executor unit test `register_custom_runner_consumes_once`) +# charges the memory limit only once, so a loop like this cannot exhaust it. +code = b'# { "Depends": "py-genlayer:test" }\nx\n' + +ids = {register_runner(code) for _ in range(1000)} +assert len(ids) == 1, ids +print(next(iter(ids))) +exit(0) From ae0e9983a7f6377ae6e4046821784b9b17c58552 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Sat, 20 Jun 2026 00:33:07 +0900 Subject: [PATCH 009/124] =?UTF-8?q?docs(build):=20document=20ya-test-runne?= =?UTF-8?q?r=20--ignore-hash=20in=20test=20skill=20=F0=9F=93=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/skills/test/SKILL.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.claude/skills/test/SKILL.md b/.claude/skills/test/SKILL.md index fcf9fff60..93fef3163 100644 --- a/.claude/skills/test/SKILL.md +++ b/.claude/skills/test/SKILL.md @@ -40,6 +40,13 @@ ya-test-runner run [OPTIONS] | `--fail-fast` | Stop execution after first failure | | `--coverage` | Enable coverage collection for Rust tests | | `--log-level LEVEL` | Set log level (trace/debug/info/warning/error) | +| `--ignore-hash` | Skip `.hash` (execution-hash) comparison entirely | + +**`--ignore-hash`:** integration cases compare both the printed semantics +(`.N.stdout`) and a deterministic execution hash (`.N.hash`). When adding a new +case, you usually don't have a correct `.hash` yet — run with `--ignore-hash` so +only the `.stdout` semantics are checked, or set `stable_hash: false` on the +entry (then validators compare to the leader's hash instead of a committed file). ### Show Information ```bash From cc8f8ee50ca2f05cfe70823f30ac19e093d3505f Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Sat, 20 Jun 2026 00:44:55 +0900 Subject: [PATCH 010/124] =?UTF-8?q?fix(wasi):=20require=20read=5Fstorage?= =?UTF-8?q?=20permission=20for=20MapFile=20gl=5Fcall=20=F0=9F=94=92?= =?UTF-8?q?=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../03-wasi_genlayer_sdk/02-gl_call.rst | 8 ++++++++ executor/src/wasi/genlayer_sdk.rs | 7 +++++++ runners/genlayer-py-std/src/genlayer/vm/__init__.py | 3 +++ 3 files changed, 18 insertions(+) diff --git a/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst b/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst index db96e67a3..be1c99009 100644 --- a/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst +++ b/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst @@ -233,6 +233,14 @@ Payload } } +Mapping into ``/vm/`` is forbidden. Resolving a ``chain:`` runner reads another +contract's storage, so this requires :ref:`gvm-perm-read-storage`. + +Requirements +~~~~~~~~~~~~ + +#. :ref:`gvm-perm-read-storage` + ``WebRender`` Message --------------------- diff --git a/executor/src/wasi/genlayer_sdk.rs b/executor/src/wasi/genlayer_sdk.rs index a87ab6959..1fb3a96c4 100644 --- a/executor/src/wasi/genlayer_sdk.rs +++ b/executor/src/wasi/genlayer_sdk.rs @@ -1632,6 +1632,13 @@ impl ContextVFS<'_> { path_in_runner: String, path_in_vfs: String, ) -> Result { + // Resolving a `chain:` runner reads another contract's storage, so this + // is gated on the same permission as `storage_read` to avoid becoming a + // read-storage bypass. + if !self.context.data.conf.can_read_storage { + return Err(generated::types::Errno::Forbidden.into()); + } + let supervisor = self.context.data.supervisor.clone(); let is_det = self.context.data.conf.is_deterministic; let limiter = supervisor.limiter.get(is_det); diff --git a/runners/genlayer-py-std/src/genlayer/vm/__init__.py b/runners/genlayer-py-std/src/genlayer/vm/__init__.py index 64b656410..f46513bfd 100644 --- a/runners/genlayer-py-std/src/genlayer/vm/__init__.py +++ b/runners/genlayer-py-std/src/genlayer/vm/__init__.py @@ -378,6 +378,9 @@ def map_file(runner: str, path_in_runner: str, path_in_vfs: str) -> None: Behaves the same as the ``MapFile`` runner action: if ``path_in_runner`` ends with ``/`` the whole directory subtree is mapped, otherwise a single file. + Requires the ``read_storage`` permission (a ``chain:`` runner reads another + contract's storage). Mapping into ``/vm/`` is forbidden. + :param runner: runner id (e.g. ``name:hash``, ``contract``, ``custom:``) :param path_in_runner: path within the runner archive :param path_in_vfs: absolute destination path in the VM filesystem From 5033d238cbb04ce2c95a07008dfade950c767039 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Sat, 20 Jun 2026 00:45:18 +0900 Subject: [PATCH 011/124] =?UTF-8?q?test(executor):=20unit-test=20parse=5Fr?= =?UTF-8?q?unner=5Fid=20+=20document=20runner=20id=20forms=20=E2=9C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../02-execution-environment/04-runners.rst | 16 ++++- executor/src/runners/mod.rs | 58 +++++++++++++++++++ 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/doc/website/src/spec/02-execution-environment/04-runners.rst b/doc/website/src/spec/02-execution-environment/04-runners.rst index 2ccc54c11..9343e6068 100644 --- a/doc/website/src/spec/02-execution-environment/04-runners.rst +++ b/doc/website/src/spec/02-execution-environment/04-runners.rst @@ -11,9 +11,19 @@ Identification and Packaging ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Each :term:`runner` is identified by ``:``. -``human-readable-id`` is provided for convenience. -``hash`` is a sha3-256 hash of its contents +A :term:`runner` is referenced by a runner id, which has one of the following +forms (see the ``runner-id`` definition in the runner.json schema): + +- ``:`` — a packaged runner. ``human-readable-id`` is + provided for convenience; ``hash`` is a hash of its contents (see `Hash Format`_). +- ``contract`` — the runner of the contract currently being executed. +- ``chain:
::`` — a runner code blob read from a storage slot + of an arbitrary contract (``a`` = accepted, ``f`` = finalized). +- ``custom:`` — a runner registered at runtime via the ``RegisterRunner`` + ``gl_call``, looked up by its hash. + +``contract``, ``chain`` and ``custom`` are reserved prefixes and cannot be used +as human-readable ids. Hash Format ~~~~~~~~~~~ diff --git a/executor/src/runners/mod.rs b/executor/src/runners/mod.rs index 02065f0aa..913e00484 100644 --- a/executor/src/runners/mod.rs +++ b/executor/src/runners/mod.rs @@ -252,3 +252,61 @@ pub fn verify_runner(runner_id: &str) -> Option<(&str, &str)> { } Some((runner_id, runner_hash)) } + +#[cfg(test)] +mod tests { + use super::*; + + fn addr40() -> String { + format!("0x{}1", "0".repeat(39)) + } + fn slot64() -> String { + format!("0x{}2", "0".repeat(63)) + } + + #[test] + fn parse_runner_id_forms() { + assert!(matches!( + parse_runner_id("contract"), + Some(RunnerId::Contract) + )); + assert!(matches!( + parse_runner_id("py-genlayer:test"), + Some(RunnerId::NameHash { .. }) + )); + assert!(matches!( + parse_runner_id("custom:deadbeef"), + Some(RunnerId::Custom { .. }) + )); + + match parse_runner_id(&format!("chain:{}:f:{}", addr40(), slot64())) { + Some(RunnerId::Chain { on, .. }) => { + assert_eq!(on, crate::public_abi::StorageType::LatestFinal) + } + _ => panic!("expected a chain runner id"), + } + match parse_runner_id(&format!("chain:{}:a:{}", addr40(), slot64())) { + Some(RunnerId::Chain { on, .. }) => { + assert_eq!(on, crate::public_abi::StorageType::LatestNonFinal) + } + _ => panic!("expected a chain runner id"), + } + } + + #[test] + fn parse_runner_id_rejects_malformed() { + assert!(parse_runner_id("custom:").is_none()); // empty hash + assert!(parse_runner_id("custom:bad/char").is_none()); // invalid char + assert!(parse_runner_id(":hash").is_none()); // empty name + assert!(parse_runner_id("name:").is_none()); // empty hash + assert!(parse_runner_id("with space:hash").is_none()); // invalid name char + + // chain: closed grammar + assert!(parse_runner_id(&format!("chain:0x01:f:{}", slot64())).is_none()); // short address + assert!(parse_runner_id(&format!("chain:{}:f:0x02", addr40())).is_none()); // short slot + assert!(parse_runner_id(&format!("chain:{}:x:{}", addr40(), slot64())).is_none()); // bad a|f + assert!(parse_runner_id(&format!("chain:{}:f:{}:extra", addr40(), slot64())).is_none()); // extra segment + assert!(parse_runner_id(&format!("chain:0x{}:f:{}", "z".repeat(40), slot64())).is_none()); + // non-hex address + } +} From 9537a049cdea8635877f8f1a2b938a7b2eb899a7 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Sat, 20 Jun 2026 17:57:41 +0900 Subject: [PATCH 012/124] =?UTF-8?q?fix(executor):=20make=20register=5Frunn?= =?UTF-8?q?ers=20opt-in=20(drop=20u=20from=20default=20permissions)=20?= =?UTF-8?q?=F0=9F=94=92=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/src/exe/run.rs | 2 +- modules/implementation/src/manager/run.rs | 2 +- tests/cases/stable/runners/map_runner_file.jsonnet | 2 +- tests/cases/stable/runners/register-runner.jsonnet | 2 +- tests/cases/stable/runners/register_loop.jsonnet | 2 +- tests/cases/stable/runners/register_no_perm.0.stdout | 2 ++ tests/cases/stable/runners/register_no_perm.jsonnet | 3 +++ tests/cases/stable/runners/register_no_perm.py | 10 ++++++++++ tests/runner/ya_test_runner_plugins/integration.py | 3 +++ 9 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 tests/cases/stable/runners/register_no_perm.0.stdout create mode 100644 tests/cases/stable/runners/register_no_perm.jsonnet create mode 100644 tests/cases/stable/runners/register_no_perm.py diff --git a/executor/src/exe/run.rs b/executor/src/exe/run.rs index 114f61b89..e7a0354c0 100644 --- a/executor/src/exe/run.rs +++ b/executor/src/exe/run.rs @@ -34,7 +34,7 @@ pub struct Args { sync: bool, #[clap( long, - default_value = "rwscnu", + default_value = "rwscn", help = "r?w?s?c?n?u?, read/write/send messages/call contracts/spawn nondet/register runners" )] permissions: String, diff --git a/modules/implementation/src/manager/run.rs b/modules/implementation/src/manager/run.rs index c23bd8863..a92cf63c2 100644 --- a/modules/implementation/src/manager/run.rs +++ b/modules/implementation/src/manager/run.rs @@ -427,7 +427,7 @@ fn default_message_fee_allocation() -> Vec String { - "rwscnu".to_owned() + "rwscn".to_owned() } impl Request { diff --git a/tests/cases/stable/runners/map_runner_file.jsonnet b/tests/cases/stable/runners/map_runner_file.jsonnet index fe80f8019..10c00840a 100644 --- a/tests/cases/stable/runners/map_runner_file.jsonnet +++ b/tests/cases/stable/runners/map_runner_file.jsonnet @@ -1,3 +1,3 @@ local simple = import 'templates/simple_deploy.jsonnet'; local util = import 'templates/util.jsonnet'; -{entry: util.addPaths([simple.run('${jsonnetDir}/map_runner_file.py') {stable_hash: false}])} +{entry: util.addPaths([simple.run('${jsonnetDir}/map_runner_file.py') {stable_hash: false, permissions: 'rwscnu'}])} diff --git a/tests/cases/stable/runners/register-runner.jsonnet b/tests/cases/stable/runners/register-runner.jsonnet index 11fce59e3..af20f0548 100644 --- a/tests/cases/stable/runners/register-runner.jsonnet +++ b/tests/cases/stable/runners/register-runner.jsonnet @@ -1,3 +1,3 @@ local simple = import 'templates/simple_deploy.jsonnet'; local util = import 'templates/util.jsonnet'; -{entry: util.addPaths([simple.run('${jsonnetDir}/register-runner.py') {stable_hash: false}])} +{entry: util.addPaths([simple.run('${jsonnetDir}/register-runner.py') {stable_hash: false, permissions: 'rwscnu'}])} diff --git a/tests/cases/stable/runners/register_loop.jsonnet b/tests/cases/stable/runners/register_loop.jsonnet index d2109338a..085594056 100644 --- a/tests/cases/stable/runners/register_loop.jsonnet +++ b/tests/cases/stable/runners/register_loop.jsonnet @@ -1,3 +1,3 @@ local simple = import 'templates/simple_deploy.jsonnet'; local util = import 'templates/util.jsonnet'; -{entry: util.addPaths([simple.run('${jsonnetDir}/register_loop.py') {stable_hash: false}])} +{entry: util.addPaths([simple.run('${jsonnetDir}/register_loop.py') {stable_hash: false, permissions: 'rwscnu'}])} diff --git a/tests/cases/stable/runners/register_no_perm.0.stdout b/tests/cases/stable/runners/register_no_perm.0.stdout new file mode 100644 index 000000000..e26bb8a09 --- /dev/null +++ b/tests/cases/stable/runners/register_no_perm.0.stdout @@ -0,0 +1,2 @@ +forbidden: SystemError +executed with `Return(null)` diff --git a/tests/cases/stable/runners/register_no_perm.jsonnet b/tests/cases/stable/runners/register_no_perm.jsonnet new file mode 100644 index 000000000..d08dc2a9a --- /dev/null +++ b/tests/cases/stable/runners/register_no_perm.jsonnet @@ -0,0 +1,3 @@ +local simple = import 'templates/simple_deploy.jsonnet'; +local util = import 'templates/util.jsonnet'; +{entry: util.addPaths([simple.run('${jsonnetDir}/register_no_perm.py') {stable_hash: false}])} diff --git a/tests/cases/stable/runners/register_no_perm.py b/tests/cases/stable/runners/register_no_perm.py new file mode 100644 index 000000000..67dbb51c2 --- /dev/null +++ b/tests/cases/stable/runners/register_no_perm.py @@ -0,0 +1,10 @@ +# { "Depends": "py-genlayer:test" } +from genlayer.vm import register_runner + +# default permissions (rwscn) do NOT grant `register_runners` (u) +try: + register_runner(b'# { "Depends": "py-genlayer:test" }\nx\n') + print('registered') +except Exception as e: + print(f'forbidden: {type(e).__name__}') +exit(0) diff --git a/tests/runner/ya_test_runner_plugins/integration.py b/tests/runner/ya_test_runner_plugins/integration.py index a83cb0df0..3e1b6897c 100644 --- a/tests/runner/ya_test_runner_plugins/integration.py +++ b/tests/runner/ya_test_runner_plugins/integration.py @@ -575,6 +575,9 @@ async def _run_single_step( request_extra = {} if 'stable' in self._test_case.description.tags: request_extra['no_modules'] = True + case_permissions = single_conf.get('permissions') + if case_permissions is not None: + request_extra['permissions'] = case_permissions dflt_bucket = 2**200 bucket_totals: list[int] = single_conf.get( 'bucket_totals', [dflt_bucket, dflt_bucket] From 3595f8871eca9cfbe67e88ba877b741cccfe12e3 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Sat, 20 Jun 2026 17:59:14 +0900 Subject: [PATCH 013/124] =?UTF-8?q?fix(executor):=20report=20dev=20major/m?= =?UTF-8?q?inor=20for=20vTEST=20version=20=F0=9F=90=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/crates/common/src/version.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/executor/crates/common/src/version.rs b/executor/crates/common/src/version.rs index 647d77ec4..232c6e5d7 100644 --- a/executor/crates/common/src/version.rs +++ b/executor/crates/common/src/version.rs @@ -73,10 +73,13 @@ impl Version { pub static CURRENT: std::sync::LazyLock = std::sync::LazyLock::new(|| { if crate::VERSION.starts_with("vTEST") { + // vTEST has no numeric build id, so report the active dev major/minor + // (see `.genvm-monorepo-root` "major-minor") with a max patch so it sorts + // newer than any real release of that line. return Version { - major: 99, - minor: 0, - patch: 0, + major: 0, + minor: 3, + patch: u16::MAX, }; } From e3b418f9e231e9e82067f197c211af3fefb32fc4 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Sat, 20 Jun 2026 18:08:22 +0900 Subject: [PATCH 014/124] =?UTF-8?q?chore(build):=20version-check=20genvm-c?= =?UTF-8?q?ommon;=20derive=20vTEST=20version=20from=20CARGO=5FPKG=5FVERSIO?= =?UTF-8?q?N=20=F0=9F=94=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-config.yaml | 2 +- executor/Cargo.lock | 2 +- executor/crates/common/Cargo.toml | 2 +- executor/crates/common/src/version.rs | 19 ++++++++++++++----- modules/implementation/Cargo.lock | 2 +- support/ci/check-versions.py | 6 +++++- 6 files changed, 23 insertions(+), 10 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 535d78c6d..bca7c536d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -87,4 +87,4 @@ repos: entry: ./support/ci/check-versions.py language: system pass_filenames: false - files: ^(executor/Cargo\.toml|modules/implementation/Cargo\.toml|\.genvm-monorepo-root)$ + files: ^(executor/Cargo\.toml|executor/crates/common/Cargo\.toml|modules/implementation/Cargo\.toml|\.genvm-monorepo-root)$ diff --git a/executor/Cargo.lock b/executor/Cargo.lock index aa0cca546..51b3d7b4b 100644 --- a/executor/Cargo.lock +++ b/executor/Cargo.lock @@ -1044,7 +1044,7 @@ dependencies = [ [[package]] name = "genvm-common" -version = "0.1.0" +version = "0.3.0" dependencies = [ "anyhow", "arbitrary", diff --git a/executor/crates/common/Cargo.toml b/executor/crates/common/Cargo.toml index d1ff41dfb..218d70b0b 100644 --- a/executor/crates/common/Cargo.toml +++ b/executor/crates/common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "genvm-common" -version = "0.1.0" +version = "0.3.0" edition = "2021" [profile.release] diff --git a/executor/crates/common/src/version.rs b/executor/crates/common/src/version.rs index 232c6e5d7..a4904a17b 100644 --- a/executor/crates/common/src/version.rs +++ b/executor/crates/common/src/version.rs @@ -73,12 +73,21 @@ impl Version { pub static CURRENT: std::sync::LazyLock = std::sync::LazyLock::new(|| { if crate::VERSION.starts_with("vTEST") { - // vTEST has no numeric build id, so report the active dev major/minor - // (see `.genvm-monorepo-root` "major-minor") with a max patch so it sorts - // newer than any real release of that line. + // vTEST has no numeric build id, so report this crate's compile-time + // version (kept at the active dev major/minor via `.genvm-monorepo-root`) + // with a max patch so it sorts newer than any real release of that line. + let mut parts = env!("CARGO_PKG_VERSION").split('.'); + let major = parts + .next() + .and_then(|x| x.parse().ok()) + .expect("CARGO_PKG_VERSION must have a numeric major"); + let minor = parts + .next() + .and_then(|x| x.parse().ok()) + .expect("CARGO_PKG_VERSION must have a numeric minor"); return Version { - major: 0, - minor: 3, + major, + minor, patch: u16::MAX, }; } diff --git a/modules/implementation/Cargo.lock b/modules/implementation/Cargo.lock index 34925db19..4efd92d77 100644 --- a/modules/implementation/Cargo.lock +++ b/modules/implementation/Cargo.lock @@ -1008,7 +1008,7 @@ dependencies = [ [[package]] name = "genvm-common" -version = "0.1.0" +version = "0.3.0" dependencies = [ "anyhow", "arbitrary", diff --git a/support/ci/check-versions.py b/support/ci/check-versions.py index badc1ca5e..a5dfcb694 100755 --- a/support/ci/check-versions.py +++ b/support/ci/check-versions.py @@ -27,7 +27,11 @@ root = pathlib.Path(__file__).resolve().parents[2] conf_path = root / '.genvm-monorepo-root' -CARGO_FILES = ['executor/Cargo.toml', 'modules/implementation/Cargo.toml'] +CARGO_FILES = [ + 'executor/Cargo.toml', + 'executor/crates/common/Cargo.toml', + 'modules/implementation/Cargo.toml', +] def load_conf(): From 74f32c2deed4d47d3b93d51e093e435787314e6a Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Sat, 20 Jun 2026 18:10:06 +0900 Subject: [PATCH 015/124] =?UTF-8?q?refactor(executor):=20make=20version::C?= =?UTF-8?q?URRENT=20a=20const=20=E2=99=BB=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/crates/common/Cargo.lock | 2 +- executor/crates/common/src/version.rs | 71 ++++++++++++++++++--------- 2 files changed, 49 insertions(+), 24 deletions(-) diff --git a/executor/crates/common/Cargo.lock b/executor/crates/common/Cargo.lock index e27cb8e67..539ec981c 100644 --- a/executor/crates/common/Cargo.lock +++ b/executor/crates/common/Cargo.lock @@ -514,7 +514,7 @@ dependencies = [ [[package]] name = "genvm-common" -version = "0.1.0" +version = "0.3.0" dependencies = [ "anyhow", "arbitrary", diff --git a/executor/crates/common/src/version.rs b/executor/crates/common/src/version.rs index a4904a17b..5b17e231a 100644 --- a/executor/crates/common/src/version.rs +++ b/executor/crates/common/src/version.rs @@ -71,20 +71,39 @@ impl Version { } } -pub static CURRENT: std::sync::LazyLock = std::sync::LazyLock::new(|| { - if crate::VERSION.starts_with("vTEST") { +/// Parses a `u16` starting at `i`, returning the value and the index past the +/// last digit consumed. +const fn parse_u16(s: &[u8], mut i: usize) -> (u16, usize) { + let mut n: u16 = 0; + while i < s.len() && s[i] >= b'0' && s[i] <= b'9' { + n = n * 10 + (s[i] - b'0') as u16; + i += 1; + } + (n, i) +} + +const fn const_starts_with(s: &[u8], prefix: &[u8]) -> bool { + if s.len() < prefix.len() { + return false; + } + let mut i = 0; + while i < prefix.len() { + if s[i] != prefix[i] { + return false; + } + i += 1; + } + true +} + +const fn current_version() -> Version { + if const_starts_with(crate::VERSION.as_bytes(), b"vTEST") { // vTEST has no numeric build id, so report this crate's compile-time // version (kept at the active dev major/minor via `.genvm-monorepo-root`) // with a max patch so it sorts newer than any real release of that line. - let mut parts = env!("CARGO_PKG_VERSION").split('.'); - let major = parts - .next() - .and_then(|x| x.parse().ok()) - .expect("CARGO_PKG_VERSION must have a numeric major"); - let minor = parts - .next() - .and_then(|x| x.parse().ok()) - .expect("CARGO_PKG_VERSION must have a numeric minor"); + let pkg = env!("CARGO_PKG_VERSION").as_bytes(); + let (major, i) = parse_u16(pkg, 0); + let (minor, _) = parse_u16(pkg, i + 1); // skip the '.' return Version { major, minor, @@ -92,15 +111,21 @@ pub static CURRENT: std::sync::LazyLock = std::sync::LazyLock::new(|| { }; } - regex::Regex::new(r"^v(\d+)\.(\d+)\.(\d+)") - .unwrap() - .captures(crate::VERSION) - .and_then(|caps| { - Some(Version { - major: caps[1].parse().ok()?, - minor: caps[2].parse().ok()?, - patch: caps[3].parse().ok()?, - }) - }) - .unwrap() -}); + // release build id is `v..-...` + let id = crate::VERSION.as_bytes(); + let start = if !id.is_empty() && id[0] == b'v' { + 1 + } else { + 0 + }; + let (major, i) = parse_u16(id, start); + let (minor, i) = parse_u16(id, i + 1); // skip '.' + let (patch, _) = parse_u16(id, i + 1); // skip '.' + Version { + major, + minor, + patch, + } +} + +pub const CURRENT: Version = current_version(); From bcfb933daf93d5a70afb882cad5bcf347c8cccfa Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Sat, 20 Jun 2026 18:19:07 +0900 Subject: [PATCH 016/124] =?UTF-8?q?feat(executor):=20add=20configurable=20?= =?UTF-8?q?code=5Fslot=20to=20contract=20root=20slot=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/codegen/data/public-abi.json | 3 ++- executor/crates/sdk-rs/src/abi/consts.rs | 7 ++++--- executor/src/host/message.rs | 6 ------ executor/src/host/mod.rs | 2 +- executor/src/rt/vm/storage.rs | 17 +++++++++++++++-- executor/src/runners/mod.rs | 2 +- .../src/genlayer/storage/root.py | 7 +++++++ .../src/genlayer/vm/public_abi.py | 1 + tests/runner/origin/public_abi.py | 1 + 9 files changed, 32 insertions(+), 14 deletions(-) diff --git a/executor/codegen/data/public-abi.json b/executor/codegen/data/public-abi.json index 9d49a4582..a983a51c9 100644 --- a/executor/codegen/data/public-abi.json +++ b/executor/codegen/data/public-abi.json @@ -49,7 +49,8 @@ "code": 1, "locked_slots": 2, "upgraders": 3, - "major": 4 + "major": 4, + "code_slot": 5 } }, { diff --git a/executor/crates/sdk-rs/src/abi/consts.rs b/executor/crates/sdk-rs/src/abi/consts.rs index ec17ae01a..6e433f510 100644 --- a/executor/crates/sdk-rs/src/abi/consts.rs +++ b/executor/crates/sdk-rs/src/abi/consts.rs @@ -163,6 +163,7 @@ pub mod root_offsets { pub const LOCKED_SLOTS: u32 = 2; pub const UPGRADERS: u32 = 3; pub const MAJOR: u32 = 4; + pub const CODE_SLOT: u32 = 5; } pub mod top_limits { @@ -308,9 +309,9 @@ pub mod __VmError { #[derive(Debug, Clone, PartialEq, Eq, Serialize)] pub struct VmError(pub Cow<'static, str>); -impl From for String { - fn from(val: VmError) -> Self { - val.0.into() +impl Into for VmError { + fn into(self) -> String { + self.0.into() } } #[rustfmt::skip] diff --git a/executor/src/host/message.rs b/executor/src/host/message.rs index 4f2dd51f0..d715de013 100644 --- a/executor/src/host/message.rs +++ b/executor/src/host/message.rs @@ -40,12 +40,6 @@ impl AccountAddress { #[repr(C)] pub struct SlotID(#[serde_as(as = "Base64")] pub [u8; 32]); -pub mod root_offsets { - pub const CODE: u32 = 1; - pub const LOCKED_SLOTS: u32 = 2; - pub const UPGRADERS: u32 = 3; -} - impl SlotID { pub const ZERO: SlotID = SlotID([0; 32]); pub const SIZE: u32 = 32; diff --git a/executor/src/host/mod.rs b/executor/src/host/mod.rs index 38147c374..b1e547486 100644 --- a/executor/src/host/mod.rs +++ b/executor/src/host/mod.rs @@ -5,10 +5,10 @@ use genlayer_sdk::abi; use genvm_common::*; use crate::public_abi; +use crate::public_abi::root_offsets; use crate::public_abi::{ResultCode, StorageType}; use genvm_common::calldata::Address; use genvm_common::calldata::ADDRESS_SIZE; -use message::root_offsets; use core::str; use std::os::fd::FromRawFd; diff --git a/executor/src/rt/vm/storage.rs b/executor/src/rt/vm/storage.rs index dfa76207e..6cc8be3ac 100644 --- a/executor/src/rt/vm/storage.rs +++ b/executor/src/rt/vm/storage.rs @@ -5,7 +5,7 @@ use const_lru::ConstLru; use genlayer_sdk::abi; use genvm_common::{calldata, sync}; -use crate::{host::message::root_offsets, rt, SlotID}; +use crate::{public_abi::root_offsets, rt, SlotID}; #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] #[repr(C)] @@ -411,10 +411,23 @@ impl Storage { &mut self, limiter: &rt::memlimiter::Limiter, ) -> anyhow::Result> { - let code_slot = SlotID::ZERO.indirection(root_offsets::CODE); + let code_slot = self.resolve_code_slot().await?; self.read_code_at(code_slot, limiter).await } + /// Resolves the slot the contract code is stored at: the raw `code_slot` root + /// field if set, otherwise the default `code` slot. + pub async fn resolve_code_slot(&mut self) -> anyhow::Result { + let mut raw = [0u8; 32]; + self.read(SlotID::ZERO, root_offsets::CODE_SLOT, &mut raw) + .await?; + if raw == [0u8; 32] { + Ok(SlotID::ZERO.indirection(root_offsets::CODE)) + } else { + Ok(SlotID::from_bytes(raw)) + } + } + pub async fn read_code_at( &mut self, code_slot: SlotID, diff --git a/executor/src/runners/mod.rs b/executor/src/runners/mod.rs index 913e00484..8a0b21892 100644 --- a/executor/src/runners/mod.rs +++ b/executor/src/runners/mod.rs @@ -155,7 +155,7 @@ pub fn get_runner_of_contract( address: calldata::Address, state: crate::public_abi::StorageType, ) -> symbol_table::GlobalSymbol { - let slot = crate::SlotID::ZERO.indirection(crate::host::message::root_offsets::CODE); + let slot = crate::SlotID::ZERO.indirection(crate::public_abi::root_offsets::CODE); symbol_table::GlobalSymbol::from(chain_canonical(address, state, slot)) } diff --git a/runners/genlayer-py-std/src/genlayer/storage/root.py b/runners/genlayer-py-std/src/genlayer/storage/root.py index 6fcae7231..4d8323197 100644 --- a/runners/genlayer-py-std/src/genlayer/storage/root.py +++ b/runners/genlayer-py-std/src/genlayer/storage/root.py @@ -44,6 +44,13 @@ class Root: Major version of the GenVM contract expects """ + code_slot: u256 + """ + Slot id the contract code is stored at, as a raw 32-byte value. If zero (the + default), the code is read from the default ``code`` slot; otherwise it is read + from the pointed-to slot (see ``chain:`` runner ids). + """ + @staticmethod def get() -> 'Root': """ diff --git a/runners/genlayer-py-std/src/genlayer/vm/public_abi.py b/runners/genlayer-py-std/src/genlayer/vm/public_abi.py index 6baf5a15b..48165578f 100644 --- a/runners/genlayer-py-std/src/genlayer/vm/public_abi.py +++ b/runners/genlayer-py-std/src/genlayer/vm/public_abi.py @@ -39,6 +39,7 @@ class _RootOffsets(typing.NamedTuple): LOCKED_SLOTS: int = 2 UPGRADERS: int = 3 MAJOR: int = 4 + CODE_SLOT: int = 5 root_offsets: typing.Final = _RootOffsets() diff --git a/tests/runner/origin/public_abi.py b/tests/runner/origin/public_abi.py index 6baf5a15b..48165578f 100644 --- a/tests/runner/origin/public_abi.py +++ b/tests/runner/origin/public_abi.py @@ -39,6 +39,7 @@ class _RootOffsets(typing.NamedTuple): LOCKED_SLOTS: int = 2 UPGRADERS: int = 3 MAJOR: int = 4 + CODE_SLOT: int = 5 root_offsets: typing.Final = _RootOffsets() From d87540809166c6f81eb808dfd5d92c40e2135346 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Sat, 20 Jun 2026 18:22:00 +0900 Subject: [PATCH 017/124] =?UTF-8?q?feat(executor):=20verify=20contract=20m?= =?UTF-8?q?ajor=20matches=20node=20version=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/codegen/data/public-abi.json | 1 + executor/crates/sdk-rs/src/abi/consts.rs | 1 + executor/src/rt/supervisor/mod.rs | 22 +++++++++++++++++++ executor/src/rt/vm/storage.rs | 9 ++++++++ .../src/genlayer/vm/public_abi.py | 3 +++ tests/runner/origin/public_abi.py | 3 +++ 6 files changed, 39 insertions(+) diff --git a/executor/codegen/data/public-abi.json b/executor/codegen/data/public-abi.json index a983a51c9..941740531 100644 --- a/executor/codegen/data/public-abi.json +++ b/executor/codegen/data/public-abi.json @@ -123,6 +123,7 @@ "absent_runner_comment", "not_utf8_text", "malformed_runner", + "major_mismatch", { "head": "wasm", "tail": ["validating", "linking", "entrypoint"] diff --git a/executor/crates/sdk-rs/src/abi/consts.rs b/executor/crates/sdk-rs/src/abi/consts.rs index 6e433f510..0cd3a393a 100644 --- a/executor/crates/sdk-rs/src/abi/consts.rs +++ b/executor/crates/sdk-rs/src/abi/consts.rs @@ -277,6 +277,7 @@ pub mod __VmError { pub const fn absent_runner_comment(&self) -> VmError { VmError(Cow::Borrowed("invalid_contract absent_runner_comment")) } pub const fn not_utf8_text(&self) -> VmError { VmError(Cow::Borrowed("invalid_contract not_utf8_text")) } pub const fn malformed_runner(&self) -> VmError { VmError(Cow::Borrowed("invalid_contract malformed_runner")) } + pub const fn major_mismatch(&self) -> VmError { VmError(Cow::Borrowed("invalid_contract major_mismatch")) } pub const fn wasm(&self) -> InvalidContractWasm { InvalidContractWasm } } diff --git a/executor/src/rt/supervisor/mod.rs b/executor/src/rt/supervisor/mod.rs index 43648374b..913f31a25 100644 --- a/executor/src/rt/supervisor/mod.rs +++ b/executor/src/rt/supervisor/mod.rs @@ -432,6 +432,28 @@ async fn apply_contract_actions_inner( contract_id: GlobalSymbol, limiter: rt::memlimiter::Limiter, ) -> anyhow::Result { + let contract_major = vm + .vm_base + .store + .data_mut() + .genlayer_ctx + .genlayer_sdk + .data + .storage + .read_major() + .await + .with_context(|| format!("reading contract major for {contract_id}"))?; + let node_major = genvm_common::version::CURRENT.major; + if contract_major as u16 != node_major { + return Err(rt::errors::VMError( + public_abi::VmError::invalid_contract().major_mismatch(), + Some(anyhow::anyhow!( + "contract major {contract_major} != node major {node_major}" + )), + ) + .into()); + } + let arch = zelf .runner_cache .get_or_create( diff --git a/executor/src/rt/vm/storage.rs b/executor/src/rt/vm/storage.rs index 6cc8be3ac..60cc19387 100644 --- a/executor/src/rt/vm/storage.rs +++ b/executor/src/rt/vm/storage.rs @@ -415,6 +415,15 @@ impl Storage { self.read_code_at(code_slot, limiter).await } + /// Reads the GenVM major version the contract was deployed for, from the + /// `major` root field (zero if never written). + pub async fn read_major(&mut self) -> anyhow::Result { + let mut buf = [0u8; 1]; + self.read(SlotID::ZERO, root_offsets::MAJOR, &mut buf) + .await?; + Ok(buf[0]) + } + /// Resolves the slot the contract code is stored at: the raw `code_slot` root /// field if set, otherwise the default `code` slot. pub async fn resolve_code_slot(&mut self) -> anyhow::Result { diff --git a/runners/genlayer-py-std/src/genlayer/vm/public_abi.py b/runners/genlayer-py-std/src/genlayer/vm/public_abi.py index 48165578f..a47567583 100644 --- a/runners/genlayer-py-std/src/genlayer/vm/public_abi.py +++ b/runners/genlayer-py-std/src/genlayer/vm/public_abi.py @@ -137,6 +137,9 @@ def not_utf8_text() -> 'VmError': def malformed_runner() -> 'VmError': return VmError('invalid_contract malformed_runner') @staticmethod + def major_mismatch() -> 'VmError': + return VmError('invalid_contract major_mismatch') + @staticmethod def wasm() -> '_VmErrorInvalidContractWasm': return _VmErrorInvalidContractWasm() diff --git a/tests/runner/origin/public_abi.py b/tests/runner/origin/public_abi.py index 48165578f..a47567583 100644 --- a/tests/runner/origin/public_abi.py +++ b/tests/runner/origin/public_abi.py @@ -137,6 +137,9 @@ def not_utf8_text() -> 'VmError': def malformed_runner() -> 'VmError': return VmError('invalid_contract malformed_runner') @staticmethod + def major_mismatch() -> 'VmError': + return VmError('invalid_contract major_mismatch') + @staticmethod def wasm() -> '_VmErrorInvalidContractWasm': return _VmErrorInvalidContractWasm() From 016fd3843c8dee50d3407f0bea183aca3412515e Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Sat, 20 Jun 2026 18:37:25 +0900 Subject: [PATCH 018/124] =?UTF-8?q?test(executor):=20cover=20major=5Fmisma?= =?UTF-8?q?tch=20reject=20and=20code=5Fslot=20redirect=20=E2=9C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../stable/runners/code_slot_redirect.0.stdout | 2 ++ .../runners/code_slot_redirect.0_0.stdout | 1 + .../stable/runners/code_slot_redirect.jsonnet | 18 ++++++++++++++++++ .../cases/stable/runners/code_slot_redirect.py | 15 +++++++++++++++ .../stable/runners/major_mismatch.0.stdout | 2 ++ .../stable/runners/major_mismatch.0_0.stdout | 1 + .../stable/runners/major_mismatch.jsonnet | 18 ++++++++++++++++++ tests/cases/stable/runners/major_mismatch.py | 15 +++++++++++++++ 8 files changed, 72 insertions(+) create mode 100644 tests/cases/stable/runners/code_slot_redirect.0.stdout create mode 100644 tests/cases/stable/runners/code_slot_redirect.0_0.stdout create mode 100644 tests/cases/stable/runners/code_slot_redirect.jsonnet create mode 100644 tests/cases/stable/runners/code_slot_redirect.py create mode 100644 tests/cases/stable/runners/major_mismatch.0.stdout create mode 100644 tests/cases/stable/runners/major_mismatch.0_0.stdout create mode 100644 tests/cases/stable/runners/major_mismatch.jsonnet create mode 100644 tests/cases/stable/runners/major_mismatch.py diff --git a/tests/cases/stable/runners/code_slot_redirect.0.stdout b/tests/cases/stable/runners/code_slot_redirect.0.stdout new file mode 100644 index 000000000..ae5576e85 --- /dev/null +++ b/tests/cases/stable/runners/code_slot_redirect.0.stdout @@ -0,0 +1,2 @@ +deployed +executed with `Return(null)` diff --git a/tests/cases/stable/runners/code_slot_redirect.0_0.stdout b/tests/cases/stable/runners/code_slot_redirect.0_0.stdout new file mode 100644 index 000000000..82f34ded9 --- /dev/null +++ b/tests/cases/stable/runners/code_slot_redirect.0_0.stdout @@ -0,0 +1 @@ +executed with `VMError("invalid_contract absent_runner_comment")` diff --git a/tests/cases/stable/runners/code_slot_redirect.jsonnet b/tests/cases/stable/runners/code_slot_redirect.jsonnet new file mode 100644 index 000000000..41e1ae7fa --- /dev/null +++ b/tests/cases/stable/runners/code_slot_redirect.jsonnet @@ -0,0 +1,18 @@ +local msg = import 'templates/message.json'; +local util = import 'templates/util.jsonnet'; +{ + entry: util.addPaths([{ + vars: {}, + code: '${jsonnetDir}/code_slot_redirect.py', + message: msg + {is_init: true}, + calldata: '{}', + stable_hash: false, + next: [{ + vars: {}, + code: null, + message: msg, + calldata: std.manifestJsonEx({method: 'foo', args: []}, ' '), + stable_hash: false, + }], + }]) +} diff --git a/tests/cases/stable/runners/code_slot_redirect.py b/tests/cases/stable/runners/code_slot_redirect.py new file mode 100644 index 000000000..9aa18e722 --- /dev/null +++ b/tests/cases/stable/runners/code_slot_redirect.py @@ -0,0 +1,15 @@ +# { "Depends": "py-genlayer:test" } +import genlayer as gl +from genlayer.storage.root import Root + + +class Contract(gl.contract.Contract): + def __init__(self): + # redirect the code slot to a different (empty) slot; the next invocation + # must read its code from there instead of the default slot + Root.get().code_slot = 12345 + print('deployed') + + @gl.public.write + def foo(self) -> None: + print('should not be reached') diff --git a/tests/cases/stable/runners/major_mismatch.0.stdout b/tests/cases/stable/runners/major_mismatch.0.stdout new file mode 100644 index 000000000..ae5576e85 --- /dev/null +++ b/tests/cases/stable/runners/major_mismatch.0.stdout @@ -0,0 +1,2 @@ +deployed +executed with `Return(null)` diff --git a/tests/cases/stable/runners/major_mismatch.0_0.stdout b/tests/cases/stable/runners/major_mismatch.0_0.stdout new file mode 100644 index 000000000..f70cfaea6 --- /dev/null +++ b/tests/cases/stable/runners/major_mismatch.0_0.stdout @@ -0,0 +1 @@ +executed with `VMError("invalid_contract major_mismatch")` diff --git a/tests/cases/stable/runners/major_mismatch.jsonnet b/tests/cases/stable/runners/major_mismatch.jsonnet new file mode 100644 index 000000000..87bd4275b --- /dev/null +++ b/tests/cases/stable/runners/major_mismatch.jsonnet @@ -0,0 +1,18 @@ +local msg = import 'templates/message.json'; +local util = import 'templates/util.jsonnet'; +{ + entry: util.addPaths([{ + vars: {}, + code: '${jsonnetDir}/major_mismatch.py', + message: msg + {is_init: true}, + calldata: '{}', + stable_hash: false, + next: [{ + vars: {}, + code: null, + message: msg, + calldata: std.manifestJsonEx({method: 'foo', args: []}, ' '), + stable_hash: false, + }], + }]) +} diff --git a/tests/cases/stable/runners/major_mismatch.py b/tests/cases/stable/runners/major_mismatch.py new file mode 100644 index 000000000..9b119bf82 --- /dev/null +++ b/tests/cases/stable/runners/major_mismatch.py @@ -0,0 +1,15 @@ +# { "Depends": "py-genlayer:test" } +import genlayer as gl +from genlayer.storage.root import Root + + +class Contract(gl.contract.Contract): + def __init__(self): + # write a major that does not match the node's, so the *next* invocation + # is rejected before it runs + Root.get().major = 5 + print('deployed') + + @gl.public.write + def foo(self) -> None: + print('should not be reached') From 5670e07e1187d0ecaa88f79899b684c36b03580d Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Sat, 20 Jun 2026 19:17:35 +0900 Subject: [PATCH 019/124] =?UTF-8?q?fix(codegen):=20emit=20From=20?= =?UTF-8?q?for=20String=20instead=20of=20Into=20=F0=9F=90=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/codegen/templates/rs.rb | 6 +++--- executor/crates/sdk-rs/src/abi/consts.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/executor/codegen/templates/rs.rb b/executor/codegen/templates/rs.rb index dbdb78234..a058f763e 100755 --- a/executor/codegen/templates/rs.rb +++ b/executor/codegen/templates/rs.rb @@ -130,9 +130,9 @@ def gen_rust_trie_builder(entries, root_name, buf) buf << "#[derive(Debug, Clone, PartialEq, Eq, Serialize)]\n" buf << "pub struct #{root_name}(pub Cow<'static, str>);\n\n" - buf << "impl Into for #{root_name} {\n" - buf << " fn into(self) -> String {\n" - buf << " self.0.into()\n" + buf << "impl From<#{root_name}> for String {\n" + buf << " fn from(val: #{root_name}) -> String {\n" + buf << " val.0.into()\n" buf << " }\n" buf << "}\n" buf << "#[rustfmt::skip]\n" diff --git a/executor/crates/sdk-rs/src/abi/consts.rs b/executor/crates/sdk-rs/src/abi/consts.rs index 0cd3a393a..7cefa1b7f 100644 --- a/executor/crates/sdk-rs/src/abi/consts.rs +++ b/executor/crates/sdk-rs/src/abi/consts.rs @@ -310,9 +310,9 @@ pub mod __VmError { #[derive(Debug, Clone, PartialEq, Eq, Serialize)] pub struct VmError(pub Cow<'static, str>); -impl Into for VmError { - fn into(self) -> String { - self.0.into() +impl From for String { + fn from(val: VmError) -> String { + val.0.into() } } #[rustfmt::skip] From 73f58f257eeebf33a95736575b6d81248c8bbbfb Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Sat, 20 Jun 2026 19:17:36 +0900 Subject: [PATCH 020/124] =?UTF-8?q?docs(spec):=20document=20root=20code=5F?= =?UTF-8?q?slot=20field=20and=20MapFile=20gl=5Fcall=20=F0=9F=93=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/adr/011. runner ids and runtime registration.md | 7 +++++++ doc/website/src/spec/04-contract-interface/03-storage.rst | 6 +++++- executor/src/runners/mod.rs | 6 ++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/doc/adr/011. runner ids and runtime registration.md b/doc/adr/011. runner ids and runtime registration.md index 032cc0955..2eba1491f 100644 --- a/doc/adr/011. runner ids and runtime registration.md +++ b/doc/adr/011. runner ids and runtime registration.md @@ -52,6 +52,13 @@ runner id. It is allowed only in deterministic mode and only when the contract holds the new `register_runners` permission (permission char `u`). A friendly `genlayer.vm.register_runner(code) -> str` wrapper is exposed in the Python SDK. +Add a companion `gl_call` `MapFile { runner, path_in_runner, path_in_vfs }` that maps +a file (or, when `path_in_runner` ends with `/`, a directory subtree) from any +runner into the VM filesystem at runtime, sharing the exact logic of the `MapFile` +runner action. Because resolving a `chain:` runner reads another contract's +storage, it requires the `read_storage` permission. Exposed as +`genlayer.vm.map_file(...)` in the Python SDK. + ## Consequences ### Positive diff --git a/doc/website/src/spec/04-contract-interface/03-storage.rst b/doc/website/src/spec/04-contract-interface/03-storage.rst index 07ee1014c..c34c219bc 100644 --- a/doc/website/src/spec/04-contract-interface/03-storage.rst +++ b/doc/website/src/spec/04-contract-interface/03-storage.rst @@ -55,8 +55,12 @@ the following data: from the contract package — see :doc:`04-upgradability` and the impl-spec for the detection flow) and read on every load so :term:`GenVM` can refuse to execute a contract whose public ABI major does not match the host's ``CURRENT_MAJOR``. +- ``code_slot``: (offset 5) A raw 32-byte :term:`SlotID`. If it is all-zero (the default), + the contract code is read from the ``code`` slot (offset 1); otherwise the code is read from + the slot it points to (same 4-byte-length-prefixed layout). This lets a contract serve its + code from an arbitrary slot, including one shared via a ``chain:
::`` runner id. -Offsets at and above ``5`` are unused by :term:`GenVM` itself and are available to the contract +Offsets at and above ``6`` are unused by :term:`GenVM` itself and are available to the contract runtime for bootstrapping its own storage (see ``Root.get_vacant_slot`` in the Python SDK). Upgrade permissions and slot locking are described in :doc:`04-upgradability`. diff --git a/executor/src/runners/mod.rs b/executor/src/runners/mod.rs index 8a0b21892..7fb7a8bc5 100644 --- a/executor/src/runners/mod.rs +++ b/executor/src/runners/mod.rs @@ -155,6 +155,12 @@ pub fn get_runner_of_contract( address: calldata::Address, state: crate::public_abi::StorageType, ) -> symbol_table::GlobalSymbol { + // This builds the cache key only; the canonical points at the default `code` + // slot and intentionally ignores a `code_slot` redirect. That is sound only + // because this is called exclusively for the *currently executing* contract, + // whose actual code is read separately via `Storage::read_code` (which DOES + // honor `code_slot`). Resolving another contract's `contract` runner this way + // would read the wrong slot — use an explicit `chain:` id for that. let slot = crate::SlotID::ZERO.indirection(crate::public_abi::root_offsets::CODE); symbol_table::GlobalSymbol::from(chain_canonical(address, state, slot)) } From d360f41420db266c83034917317d0363efc10f1a Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Sat, 20 Jun 2026 19:18:55 +0900 Subject: [PATCH 021/124] =?UTF-8?q?test(executor):=20cover=20map=5Ffile=20?= =?UTF-8?q?refused=20without=20read=5Fstorage=20=E2=9C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/cases/stable/runners/map_no_read_perm.0.stdout | 2 ++ tests/cases/stable/runners/map_no_read_perm.jsonnet | 3 +++ tests/cases/stable/runners/map_no_read_perm.py | 10 ++++++++++ 3 files changed, 15 insertions(+) create mode 100644 tests/cases/stable/runners/map_no_read_perm.0.stdout create mode 100644 tests/cases/stable/runners/map_no_read_perm.jsonnet create mode 100644 tests/cases/stable/runners/map_no_read_perm.py diff --git a/tests/cases/stable/runners/map_no_read_perm.0.stdout b/tests/cases/stable/runners/map_no_read_perm.0.stdout new file mode 100644 index 000000000..e26bb8a09 --- /dev/null +++ b/tests/cases/stable/runners/map_no_read_perm.0.stdout @@ -0,0 +1,2 @@ +forbidden: SystemError +executed with `Return(null)` diff --git a/tests/cases/stable/runners/map_no_read_perm.jsonnet b/tests/cases/stable/runners/map_no_read_perm.jsonnet new file mode 100644 index 000000000..67869cf15 --- /dev/null +++ b/tests/cases/stable/runners/map_no_read_perm.jsonnet @@ -0,0 +1,3 @@ +local simple = import 'templates/simple_deploy.jsonnet'; +local util = import 'templates/util.jsonnet'; +{entry: util.addPaths([simple.run('${jsonnetDir}/map_no_read_perm.py') {stable_hash: false, permissions: 'wscn'}])} diff --git a/tests/cases/stable/runners/map_no_read_perm.py b/tests/cases/stable/runners/map_no_read_perm.py new file mode 100644 index 000000000..17737d5fb --- /dev/null +++ b/tests/cases/stable/runners/map_no_read_perm.py @@ -0,0 +1,10 @@ +# { "Depends": "py-genlayer:test" } +from genlayer.vm import map_file + +# permissions for this case omit `r` (read_storage), so map_file must be refused +try: + map_file('contract', 'file', '/mapped') + print('mapped') +except Exception as e: + print(f'forbidden: {type(e).__name__}') +exit(0) From a100a6c4e8247e29fd7278ba2fc424514808fb2a Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Sat, 20 Jun 2026 19:20:28 +0900 Subject: [PATCH 022/124] =?UTF-8?q?docs(spec):=20reserved=20root=20offsets?= =?UTF-8?q?=20must=20stay=20zero=20for=20forward-compat=20=F0=9F=93=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/website/src/spec/04-contract-interface/03-storage.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/website/src/spec/04-contract-interface/03-storage.rst b/doc/website/src/spec/04-contract-interface/03-storage.rst index c34c219bc..1dc805332 100644 --- a/doc/website/src/spec/04-contract-interface/03-storage.rst +++ b/doc/website/src/spec/04-contract-interface/03-storage.rst @@ -60,7 +60,10 @@ the following data: the slot it points to (same 4-byte-length-prefixed layout). This lets a contract serve its code from an arbitrary slot, including one shared via a ``chain:
::`` runner id. -Offsets at and above ``6`` are unused by :term:`GenVM` itself and are available to the contract -runtime for bootstrapping its own storage (see ``Root.get_vacant_slot`` in the Python SDK). +Offsets at and above ``6`` are reserved for future :term:`GenVM` use and should remain zero: +a contract must not store data in them, otherwise a future :term:`GenVM` version that starts +reading those offsets may break the contract. Contract runtimes that need scratch space for +bootstrapping should derive a separate sub-slot instead (see ``Root.get_vacant_slot`` in the +Python SDK). Upgrade permissions and slot locking are described in :doc:`04-upgradability`. From 7920346aff2ed9e2427574740ae3863f0d3c05fb Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Sat, 20 Jun 2026 19:28:58 +0900 Subject: [PATCH 023/124] =?UTF-8?q?docs(spec):=20correct=20code=5Fslot=20b?= =?UTF-8?q?yte=20span=20(5-36)=20and=20cache-key=20note=20=F0=9F=93=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/spec/04-contract-interface/03-storage.rst | 5 ++++- executor/src/runners/mod.rs | 11 +++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/doc/website/src/spec/04-contract-interface/03-storage.rst b/doc/website/src/spec/04-contract-interface/03-storage.rst index 1dc805332..19a061244 100644 --- a/doc/website/src/spec/04-contract-interface/03-storage.rst +++ b/doc/website/src/spec/04-contract-interface/03-storage.rst @@ -60,7 +60,10 @@ the following data: the slot it points to (same 4-byte-length-prefixed layout). This lets a contract serve its code from an arbitrary slot, including one shared via a ``chain:
::`` runner id. -Offsets at and above ``6`` are reserved for future :term:`GenVM` use and should remain zero: +Offsets are byte offsets into the root slot, so ``code_slot`` (32 bytes) occupies offsets ``5`` +through ``36``; the next field would start at offset ``37``. + +Offsets at and above ``37`` are reserved for future :term:`GenVM` use and should remain zero: a contract must not store data in them, otherwise a future :term:`GenVM` version that starts reading those offsets may break the contract. Contract runtimes that need scratch space for bootstrapping should derive a separate sub-slot instead (see ``Root.get_vacant_slot`` in the diff --git a/executor/src/runners/mod.rs b/executor/src/runners/mod.rs index 7fb7a8bc5..16cbbfa4f 100644 --- a/executor/src/runners/mod.rs +++ b/executor/src/runners/mod.rs @@ -155,12 +155,11 @@ pub fn get_runner_of_contract( address: calldata::Address, state: crate::public_abi::StorageType, ) -> symbol_table::GlobalSymbol { - // This builds the cache key only; the canonical points at the default `code` - // slot and intentionally ignores a `code_slot` redirect. That is sound only - // because this is called exclusively for the *currently executing* contract, - // whose actual code is read separately via `Storage::read_code` (which DOES - // honor `code_slot`). Resolving another contract's `contract` runner this way - // would read the wrong slot — use an explicit `chain:` id for that. + // This is only the cache key for the contract's runner archive; it always + // uses the default `code` slot, even when the contract set a `code_slot` + // redirect. That is fine: the key only needs to be unique per (address, + // state), and the actual code is read by `Storage::read_code`, which honors + // `code_slot`. The key is not a code location. let slot = crate::SlotID::ZERO.indirection(crate::public_abi::root_offsets::CODE); symbol_table::GlobalSymbol::from(chain_canonical(address, state, slot)) } From c9d2f0da0536b1605891b4aa13d694313b31fd8b Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Sat, 20 Jun 2026 19:29:14 +0900 Subject: [PATCH 024/124] =?UTF-8?q?test(executor):=20exec=20redirected=20c?= =?UTF-8?q?ode=20via=20code=5Fslot=20(fails=20if=20ignored)=20=E2=9C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../stable/runners/code_slot_exec.0.stdout | 2 ++ .../stable/runners/code_slot_exec.0_0.stdout | 2 ++ .../stable/runners/code_slot_exec.jsonnet | 18 +++++++++++++++ tests/cases/stable/runners/code_slot_exec.py | 23 +++++++++++++++++++ 4 files changed, 45 insertions(+) create mode 100644 tests/cases/stable/runners/code_slot_exec.0.stdout create mode 100644 tests/cases/stable/runners/code_slot_exec.0_0.stdout create mode 100644 tests/cases/stable/runners/code_slot_exec.jsonnet create mode 100644 tests/cases/stable/runners/code_slot_exec.py diff --git a/tests/cases/stable/runners/code_slot_exec.0.stdout b/tests/cases/stable/runners/code_slot_exec.0.stdout new file mode 100644 index 000000000..ae5576e85 --- /dev/null +++ b/tests/cases/stable/runners/code_slot_exec.0.stdout @@ -0,0 +1,2 @@ +deployed +executed with `Return(null)` diff --git a/tests/cases/stable/runners/code_slot_exec.0_0.stdout b/tests/cases/stable/runners/code_slot_exec.0_0.stdout new file mode 100644 index 000000000..2d08fba0a --- /dev/null +++ b/tests/cases/stable/runners/code_slot_exec.0_0.stdout @@ -0,0 +1,2 @@ +hello from code_slot +executed with `Return(null)` diff --git a/tests/cases/stable/runners/code_slot_exec.jsonnet b/tests/cases/stable/runners/code_slot_exec.jsonnet new file mode 100644 index 000000000..505148a9f --- /dev/null +++ b/tests/cases/stable/runners/code_slot_exec.jsonnet @@ -0,0 +1,18 @@ +local msg = import 'templates/message.json'; +local util = import 'templates/util.jsonnet'; +{ + entry: util.addPaths([{ + vars: {}, + code: '${jsonnetDir}/code_slot_exec.py', + message: msg + {is_init: true}, + calldata: '{}', + stable_hash: false, + next: [{ + vars: {}, + code: null, + message: msg, + calldata: std.manifestJsonEx({method: 'foo', args: []}, ' '), + stable_hash: false, + }], + }]) +} diff --git a/tests/cases/stable/runners/code_slot_exec.py b/tests/cases/stable/runners/code_slot_exec.py new file mode 100644 index 000000000..b0f00fe45 --- /dev/null +++ b/tests/cases/stable/runners/code_slot_exec.py @@ -0,0 +1,23 @@ +# { "Depends": "py-genlayer:test" } +import genlayer as gl +from genlayer.storage.root import Root + + +class Contract(gl.contract.Contract): + def __init__(self): + # write a *different* valid contract to slot 7 and point code_slot at it; + # the next invocation must load and run THAT code, not this class's `foo`. + alt = ( + b'# { "Depends": "py-genlayer:test" }\nprint("hello from code_slot")\nexit(0)\n' + ) + slot_id = bytes([7]) + bytes(31) + s = Root.MANAGER.get_store_slot(slot_id) + s.write(0, len(alt).to_bytes(4, 'little')) + s.write(4, alt) + Root.get().code_slot = int.from_bytes(slot_id, 'little') + print('deployed') + + @gl.public.write + def foo(self) -> None: + # only reached if code_slot was IGNORED (default code loaded) + print('original foo ran -- code_slot ignored!') From cfd150b7b444febe976197f1156fc0a6e8175f51 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Sat, 20 Jun 2026 19:41:14 +0900 Subject: [PATCH 025/124] =?UTF-8?q?test(executor):=20map=5Ffile(contract)?= =?UTF-8?q?=20uses=20preloaded=20archive=20after=20code=20relocation=20?= =?UTF-8?q?=E2=9C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../runners/map_contract_relocated.0.stdout | 2 + .../runners/map_contract_relocated.0_0.stdout | 2 + .../runners/map_contract_relocated.jsonnet | 18 +++++++++ .../stable/runners/map_contract_relocated.py | 37 +++++++++++++++++++ 4 files changed, 59 insertions(+) create mode 100644 tests/cases/stable/runners/map_contract_relocated.0.stdout create mode 100644 tests/cases/stable/runners/map_contract_relocated.0_0.stdout create mode 100644 tests/cases/stable/runners/map_contract_relocated.jsonnet create mode 100644 tests/cases/stable/runners/map_contract_relocated.py diff --git a/tests/cases/stable/runners/map_contract_relocated.0.stdout b/tests/cases/stable/runners/map_contract_relocated.0.stdout new file mode 100644 index 000000000..ae5576e85 --- /dev/null +++ b/tests/cases/stable/runners/map_contract_relocated.0.stdout @@ -0,0 +1,2 @@ +deployed +executed with `Return(null)` diff --git a/tests/cases/stable/runners/map_contract_relocated.0_0.stdout b/tests/cases/stable/runners/map_contract_relocated.0_0.stdout new file mode 100644 index 000000000..c66dd3351 --- /dev/null +++ b/tests/cases/stable/runners/map_contract_relocated.0_0.stdout @@ -0,0 +1,2 @@ +ok=True +executed with `Return(null)` diff --git a/tests/cases/stable/runners/map_contract_relocated.jsonnet b/tests/cases/stable/runners/map_contract_relocated.jsonnet new file mode 100644 index 000000000..24753cea9 --- /dev/null +++ b/tests/cases/stable/runners/map_contract_relocated.jsonnet @@ -0,0 +1,18 @@ +local msg = import 'templates/message.json'; +local util = import 'templates/util.jsonnet'; +{ + entry: util.addPaths([{ + vars: {}, + code: '${jsonnetDir}/map_contract_relocated.py', + message: msg + {is_init: true}, + calldata: '{}', + stable_hash: false, + next: [{ + vars: {}, + code: null, + message: msg, + calldata: std.manifestJsonEx({method: 'foo', args: []}, ' '), + stable_hash: false, + }], + }]) +} diff --git a/tests/cases/stable/runners/map_contract_relocated.py b/tests/cases/stable/runners/map_contract_relocated.py new file mode 100644 index 000000000..8e0c5e258 --- /dev/null +++ b/tests/cases/stable/runners/map_contract_relocated.py @@ -0,0 +1,37 @@ +# { "Depends": "py-genlayer:test" } +import genlayer as gl +from genlayer.storage.root import Root +from genlayer.vm import public_abi + +# the relocated contract: a script that maps its OWN runner ("contract") and +# checks it received real code. If `map_file("contract")` re-read the (wiped) +# default code slot it would get 0 bytes here. +C2 = ( + b'# { "Depends": "py-genlayer:test" }\n' + b'import genlayer as gl\n' + b'from genlayer.vm import map_file\n' + b'class Contract(gl.contract.Contract):\n' + b'\t@gl.public.write\n' + b'\tdef foo(self):\n' + b'\t\tmap_file("contract", "file", "/x")\n' + b'\t\td = open("/x", "rb").read()\n' + b'\t\tprint("ok=" + str(len(d) > 0 and d[:3] == b"# {"))\n' +) + + +class Contract(gl.contract.Contract): + def __init__(self): + # move the code to slot 7, point code_slot there, then wipe the default + # code slot (offset 1) + sid = bytes([7]) + bytes(31) + s = Root.MANAGER.get_store_slot(sid) + s.write(0, len(C2).to_bytes(4, 'little')) + s.write(4, C2) + Root.get().code_slot = int.from_bytes(sid, 'little') + default = Root.get().slot().indirect(public_abi.root_offsets.CODE) + default.write(0, (0).to_bytes(4, 'little')) + print('deployed') + + @gl.public.write + def foo(self) -> None: + print('C1.foo should not run') From 1d001790bcb3349f568b79019dc6a78c97a58f77 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Sat, 20 Jun 2026 19:43:52 +0900 Subject: [PATCH 026/124] =?UTF-8?q?refactor(wasi):=20move=20MapFile=20runn?= =?UTF-8?q?er=20resolution=20out=20of=20vfs=20into=20actions=20=E2=99=BB?= =?UTF-8?q?=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/src/rt/supervisor/actions.rs | 28 +++++++++++++++++++++++++++ executor/src/wasi/genlayer_sdk.rs | 23 ++++++---------------- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/executor/src/rt/supervisor/actions.rs b/executor/src/rt/supervisor/actions.rs index 06afc93ff..bb75b0406 100644 --- a/executor/src/rt/supervisor/actions.rs +++ b/executor/src/rt/supervisor/actions.rs @@ -298,6 +298,34 @@ pub(crate) fn map_archive_file( Ok(()) } +/// Resolves `runner` (relative to the contract at `contract_address`) and maps +/// one of its files into `preview1` at runtime. This keeps all runner-resolution +/// knowledge in this module: callers (e.g. the `MapFile` `gl_call`) only supply +/// VM context and delegate, instead of stitching the resolution together +/// themselves. +#[allow(clippy::too_many_arguments)] +pub(crate) async fn map_runner_file( + supervisor: &rt::supervisor::Supervisor, + preview1: &mut crate::wasi::preview1::Context, + limiter: &rt::memlimiter::Limiter, + contract_address: calldata::Address, + state: public_abi::StorageType, + runner: symbol_table::GlobalSymbol, + path_in_runner: &str, + path_in_vfs: &str, +) -> anyhow::Result<()> { + let contract_id = runners::get_runner_of_contract(contract_address, state); + let (_id, arch) = load_runner(supervisor, contract_id, limiter, runner).await?; + map_archive_file( + preview1, + limiter, + &supervisor.shared_data.cancellation, + &arch, + path_in_runner, + path_in_vfs, + ) +} + impl Ctx<'_, '_> { fn resolve_runner(&self, id: symbol_table::GlobalSymbol) -> anyhow::Result { resolve_runner(self.supervisor, self.contract_id, id) diff --git a/executor/src/wasi/genlayer_sdk.rs b/executor/src/wasi/genlayer_sdk.rs index 1fb3a96c4..1674619bd 100644 --- a/executor/src/wasi/genlayer_sdk.rs +++ b/executor/src/wasi/genlayer_sdk.rs @@ -1642,31 +1642,20 @@ impl ContextVFS<'_> { let supervisor = self.context.data.supervisor.clone(); let is_det = self.context.data.conf.is_deterministic; let limiter = supervisor.limiter.get(is_det); - let contract_address = self.context.data.message_data.message.contract_address; - let contract_id = crate::runners::get_runner_of_contract( - contract_address, - self.context.data.conf.state_mode, - ); + let state = self.context.data.conf.state_mode; - let (_id, arch) = crate::rt::supervisor::actions::load_runner( + crate::rt::supervisor::actions::map_runner_file( &supervisor, - contract_id, - limiter, - symbol_table::GlobalSymbol::from(runner), - ) - .await - .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?; - - let cancellation = supervisor.shared_data.cancellation.clone(); - crate::rt::supervisor::actions::map_archive_file( self.preview1, limiter, - &cancellation, - &arch, + contract_address, + state, + symbol_table::GlobalSymbol::from(runner), &path_in_runner, &path_in_vfs, ) + .await .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?; Ok(file_fd_none()) From 4f3ac4c72854106786ac4c5e83a1cf75b9cdcd4f Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Sat, 20 Jun 2026 19:43:53 +0900 Subject: [PATCH 027/124] =?UTF-8?q?chore(claude):=20reviewer-implementatio?= =?UTF-8?q?n=20enforces=20responsibility=20encapsulation=20=F0=9F=A4=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/agents/reviewer-implementation.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.claude/agents/reviewer-implementation.md b/.claude/agents/reviewer-implementation.md index 8330178ba..e9756f396 100644 --- a/.claude/agents/reviewer-implementation.md +++ b/.claude/agents/reviewer-implementation.md @@ -40,6 +40,20 @@ Diff against the active dev branch, not `main`: doing what the loader already does is a finding — name the function it should route through. + **Responsibilities must be encapsulated in the layer that owns them.** Each + layer does its own job and exposes ONE entry point; callers in other layers + delegate, they don't reach across and re-orchestrate. Concretely: the + wasi/vfs layer (`wasi/genlayer_sdk.rs`, `wasi/preview1.rs`) is a thin syscall + shim — it must NOT contain runner-resolution logic (computing a contract's + runner id, picking storage slots/state, stitching together + `get_runner_of_contract` + `load_runner` + archive mapping). That belongs in + the runners/supervisor layer; the gl_call handler should call a single + encapsulated function there. A handler that assembles a cross-layer flow + inline (even if each piece is "shared") is a finding — name the boundary it + violates and the single function it should call instead. Likewise, storage + layout, permission derivation, and limiter accounting each have one home; + flag logic that leaks into a layer that shouldn't know about it. + 4. **Correctness & quality.** Panics on malformed input (`slice`, `unwrap`), error handling, idempotency. From 87176ba2b689df8446e542000a7cd0c43c7830e1 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Mon, 22 Jun 2026 20:17:39 +0900 Subject: [PATCH 028/124] =?UTF-8?q?refactor(wasi):=20add=20vfs::Fd=20newty?= =?UTF-8?q?pe=20and=20FileContents::from(Bytes)=20helper=20=E2=99=BB?= =?UTF-8?q?=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Collapse repeated FileContents { pos: 0, release_memory: true } construction into a From impl plus ContextVFS::place_content, and wrap raw descriptor integers in a vfs::Fd(u32) newtype. --- executor/src/wasi/genlayer_sdk.rs | 122 +++++++++--------------------- executor/src/wasi/preview1.rs | 25 ++++-- executor/src/wasi/vfs.rs | 55 ++++++++++---- 3 files changed, 95 insertions(+), 107 deletions(-) diff --git a/executor/src/wasi/genlayer_sdk.rs b/executor/src/wasi/genlayer_sdk.rs index 1674619bd..e3311b777 100644 --- a/executor/src/wasi/genlayer_sdk.rs +++ b/executor/src/wasi/genlayer_sdk.rs @@ -11,7 +11,7 @@ use wiggle::GuestError; use crate::host::{self, SlotID}; use crate::wasi::json_to_calldata::json_map_to_calldata; -use crate::{anyhow_to_wasmtime, calldata, public_abi, rt}; +use crate::{anyhow_to_wasmtime, calldata, public_abi, rt, wasi}; use genlayer_calldata::codec::Encode; pub use genlayer_sdk::abi::entry::ExtendedMessage; @@ -308,6 +308,18 @@ pub(crate) mod generated { }); } +impl From for generated::types::Fd { + fn from(fd: wasi::vfs::Fd) -> Self { + fd.as_u32().into() + } +} + +impl From for wasi::vfs::Fd { + fn from(fd: generated::types::Fd) -> Self { + wasi::vfs::Fd::new(fd.into()) + } +} + fn read_addr_from_mem( mem: &mut wiggle::GuestMemory<'_>, addr: wiggle::GuestPtr, @@ -449,6 +461,16 @@ impl From for generated::types::Error { } impl ContextVFS<'_> { + fn place_content( + &mut self, + content: vfs::FileContents, + ) -> Result { + self.vfs + .place_content(content) + .map(generated::types::Fd::from) + .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e))) + } + fn set_vm_run_result( &mut self, data: rt::vm::RunOk, @@ -463,18 +485,8 @@ impl ContextVFS<'_> { }; let data: Vec = data.as_bytes(); let len = data.len(); - Ok(( - generated::types::Fd::from( - self.vfs - .place_content(vfs::FileContents { - contents: bytes::Bytes::from(data), - pos: 0, - release_memory: true, - }) - .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?, - ), - len, - )) + self.place_content(vfs::FileContents::from(bytes::Bytes::from(data))) + .map(|fd| (fd, len)) } } @@ -658,21 +670,13 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { } let supervisor = self.context.data.supervisor.clone(); - let res = supervisor + let data = supervisor .host .lock_for(host::host_fns::Methods::EthCall) .await .eth_call(address, &calldata) .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?; - Ok(generated::types::Fd::from( - self.vfs - .place_content(vfs::FileContents { - contents: bytes::Bytes::from(res), - pos: 0, - release_memory: true, - }) - .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?, - )) + self.place_content(vfs::FileContents::from(bytes::Bytes::from(data))) } gl_call::Message::CallContract { address, @@ -1092,15 +1096,7 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { .await .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?; - Ok(generated::types::Fd::from( - self.vfs - .place_content(vfs::FileContents { - contents: bytes::Bytes::from(task), - pos: 0, - release_memory: true, - }) - .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?, - )) + self.place_content(vfs::FileContents::from(bytes::Bytes::from(task))) } gl_call::Message::WebRequest(request_payload) => { let is_det = self.context.data.conf.is_deterministic; @@ -1138,15 +1134,7 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { .await .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?; - Ok(generated::types::Fd::from( - self.vfs - .place_content(vfs::FileContents { - contents: bytes::Bytes::from(task), - pos: 0, - release_memory: true, - }) - .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?, - )) + self.place_content(vfs::FileContents::from(bytes::Bytes::from(task))) } gl_call::Message::ExecPrompt(prompt_payload) => { if self.context.data.conf.is_deterministic { @@ -1234,15 +1222,7 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { .await .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?; - Ok(generated::types::Fd::from( - self.vfs - .place_content(vfs::FileContents { - contents: bytes::Bytes::from(task), - pos: 0, - release_memory: true, - }) - .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?, - )) + self.place_content(vfs::FileContents::from(bytes::Bytes::from(task))) } gl_call::Message::ExecPromptTemplate(prompt_template_payload) => { if self.context.data.conf.is_deterministic { @@ -1318,15 +1298,7 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { .await .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?; - Ok(generated::types::Fd::from( - self.vfs - .place_content(vfs::FileContents { - contents: bytes::Bytes::from(task), - pos: 0, - release_memory: true, - }) - .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?, - )) + self.place_content(vfs::FileContents::from(bytes::Bytes::from(task))) } #[allow(deprecated)] gl_call::Message::Rollback(msg) => Err(generated::types::Error::trap( @@ -1584,15 +1556,7 @@ impl ContextVFS<'_> { let data = calldata::encode(&calldata::Value::Number(num_bigint::BigInt::from( elapsed_micros, ))); - Ok(generated::types::Fd::from( - self.vfs - .place_content(vfs::FileContents { - contents: bytes::Bytes::from(data), - pos: 0, - release_memory: true, - }) - .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?, - )) + self.place_content(vfs::FileContents::from(bytes::Bytes::from(data))) } } } @@ -1615,15 +1579,7 @@ impl ContextVFS<'_> { .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?; let data = calldata::encode(&calldata::Value::Str(id.as_str().to_owned())); - Ok(generated::types::Fd::from( - self.vfs - .place_content(vfs::FileContents { - contents: bytes::Bytes::from(data), - pos: 0, - release_memory: true, - }) - .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?, - )) + self.place_content(vfs::FileContents::from(bytes::Bytes::from(data))) } async fn map_file( @@ -1645,7 +1601,7 @@ impl ContextVFS<'_> { let contract_address = self.context.data.message_data.message.contract_address; let state = self.context.data.conf.state_mode; - crate::rt::supervisor::actions::map_runner_file( + rt::supervisor::actions::map_runner_file( &supervisor, self.preview1, limiter, @@ -1941,14 +1897,6 @@ impl ContextVFS<'_> { self.context.data.storage = my_res.vm_data.storage; let data: Vec = my_res.run_ok.as_bytes(); - Ok(generated::types::Fd::from( - self.vfs - .place_content(vfs::FileContents { - contents: bytes::Bytes::from(data), - pos: 0, - release_memory: true, - }) - .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?, - )) + self.place_content(vfs::FileContents::from(bytes::Bytes::from(data))) } } diff --git a/executor/src/wasi/preview1.rs b/executor/src/wasi/preview1.rs index 94f1ac18b..4ea21b9c4 100644 --- a/executor/src/wasi/preview1.rs +++ b/executor/src/wasi/preview1.rs @@ -9,7 +9,7 @@ use genvm_common::*; use super::vfs; use crate::{ rt, - wasi::{base, common::align_slice}, + wasi::{self, base, common::align_slice}, }; use std::collections::BTreeMap; @@ -93,6 +93,18 @@ pub(crate) mod generated { }); } +impl From for generated::types::Fd { + fn from(fd: wasi::vfs::Fd) -> Self { + fd.as_u32().into() + } +} + +impl From for wasi::vfs::Fd { + fn from(fd: generated::types::Fd) -> Self { + wasi::vfs::Fd::new(fd.into()) + } +} + impl wiggle::GuestErrorType for generated::types::Errno { fn success() -> Self { Self::Success @@ -434,7 +446,7 @@ impl generated::wasi_snapshot_preview1::WasiSnapshotPreview1 for ContextVFS<'_> _memory: &mut GuestMemory<'_>, fd: generated::types::Fd, ) -> impl std::future::Future> + Send { - let fdi: u32 = fd.into(); + let fdi = fd.into(); let res = if self.vfs.pop_fd(fdi).is_none() { Err(generated::types::Errno::Badf.into()) } else { @@ -1005,7 +1017,7 @@ impl generated::wasi_snapshot_preview1::WasiSnapshotPreview1 for ContextVFS<'_> flags: generated::types::Lookupflags, path: GuestPtr, ) -> Result { - let fdi: u32 = dirfd.into(); + let fdi = dirfd.into(); let path = super::common::read_string(memory, path)?; let Some(vfs::FileDescriptor::Dir { path: dir_path }) = self.vfs.fds.get(&fdi) else { return Err(generated::types::Errno::Badf.into()); @@ -1086,8 +1098,7 @@ impl generated::wasi_snapshot_preview1::WasiSnapshotPreview1 for ContextVFS<'_> fdflags: generated::types::Fdflags, ) -> Result { let file_path = super::common::read_string(memory, path)?; - let fdi: u32 = dirfd.into(); - let fdi: u32 = dirfd.into(); + let fdi = dirfd.into(); let new_fd = self .vfs .alloc_fd() @@ -1345,7 +1356,7 @@ impl ContextVFS<'_> { &self, fd: generated::types::Fd, ) -> Result<&vfs::FileDescriptor, generated::types::Error> { - let fdi: u32 = fd.into(); + let fdi = fd.into(); match self.vfs.fds.get(&fdi) { Some(x) => Ok(x), None => Err(generated::types::Errno::Badf.into()), @@ -1356,7 +1367,7 @@ impl ContextVFS<'_> { &mut self, fd: generated::types::Fd, ) -> Result<&mut vfs::FileDescriptor, generated::types::Error> { - let fdi: u32 = fd.into(); + let fdi = fd.into(); match self.vfs.fds.get_mut(&fdi) { Some(x) => Ok(x), None => Err(generated::types::Errno::Badf.into()), diff --git a/executor/src/wasi/vfs.rs b/executor/src/wasi/vfs.rs index 32f4b8e7b..e28dfe2b0 100644 --- a/executor/src/wasi/vfs.rs +++ b/executor/src/wasi/vfs.rs @@ -12,6 +12,16 @@ pub struct FileContents { pub release_memory: bool, } +impl From for FileContents { + fn from(value: bytes::Bytes) -> Self { + Self { + contents: value, + pos: 0, + release_memory: true, + } + } +} + pub enum FileDescriptor { Stdin, Stdout, @@ -24,13 +34,32 @@ pub enum FileDescriptor { const _: FileDescriptor = FileDescriptor::Stdin; pub(crate) struct VFS { - pub fds: BTreeMap, - pub free_descriptors: Vec, - pub next_free_descriptor: u32, + pub fds: BTreeMap, + pub free_descriptors: Vec, + pub next_free_descriptor: Fd, pub limiter: rt::memlimiter::Limiter, } +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct Fd(u32); + +impl From for u32 { + fn from(value: Fd) -> Self { + value.0 + } +} + +impl Fd { + pub fn new(fd: u32) -> Self { + Self(fd) + } + + pub fn as_u32(&self) -> u32 { + self.0 + } +} + impl VFS { pub fn new( stdin: Vec, @@ -49,18 +78,18 @@ impl VFS { let fds = BTreeMap::from([ ( - 0, + Fd::new(0), FileDescriptor::File(FileContents { contents: stdin_data, pos: 0, release_memory: true, }), ), - (1, FileDescriptor::Stdout), - (2, FileDescriptor::Stderr), - (3, FileDescriptor::Dir { path: Vec::new() }), + (Fd::new(1), FileDescriptor::Stdout), + (Fd::new(2), FileDescriptor::Stderr), + (Fd::new(3), FileDescriptor::Dir { path: Vec::new() }), ]); - let next_free_descriptor = fds.last_key_value().map(|x| *x.0).unwrap_or(0); + let next_free_descriptor = fds.last_key_value().map(|x| *x.0).unwrap_or(Fd::default()); Ok(Self { fds, next_free_descriptor, @@ -70,7 +99,7 @@ impl VFS { } /// gives vacant fd - pub fn alloc_fd(&mut self) -> anyhow::Result { + pub fn alloc_fd(&mut self) -> anyhow::Result { if self.fds.len() >= public_abi::top_limits::MAX_FDS as usize { return Err( rt::errors::VMError(abi::consts::VmError::oom().ram().limit(), None).into(), @@ -87,18 +116,18 @@ impl VFS { rt::errors::VMError(abi::consts::VmError::oom().ram().val(), None).into(), ); } - self.next_free_descriptor += 1; + self.next_free_descriptor.0 += 1; Ok(self.next_free_descriptor) } } } /// it must be removed from fds beforehand - pub fn free_fd(&mut self, fd: u32) { + pub fn free_fd(&mut self, fd: Fd) { self.free_descriptors.push(fd); } - pub fn pop_fd(&mut self, fd: u32) -> Option { + pub fn pop_fd(&mut self, fd: Fd) -> Option { match self.fds.remove(&fd) { Some(v) => { if let FileDescriptor::File(v) = &v { @@ -115,7 +144,7 @@ impl VFS { } } - pub fn place_content(&mut self, value: FileContents) -> anyhow::Result { + pub fn place_content(&mut self, value: FileContents) -> anyhow::Result { if value.release_memory && !self.limiter.consume(value.contents.len() as u32) { return Err(rt::errors::VMError(abi::consts::VmError::oom().ram().val(), None).into()); } From d5be0ded3fd7d0da9ecd7c9574a4660a59b01d13 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Mon, 22 Jun 2026 20:25:13 +0900 Subject: [PATCH 029/124] =?UTF-8?q?refactor(runners):=20add=20Slot.cast=20?= =?UTF-8?q?and=20route=20cast=5Fslot=20through=20it=20=E2=99=BB=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the storage-cast logic onto Slot.cast(t, offset) so cast_slot delegates to it, and update map_contract_relocated to build the code VLA via cast/assign and truncate the default code slot instead of writing raw length-prefixed bytes. --- .../src/genlayer/storage/__init__.py | 9 ++---- .../src/genlayer/storage/core.py | 12 +++++++ .../stable/runners/map_contract_relocated.py | 31 +++++++++---------- 3 files changed, 29 insertions(+), 23 deletions(-) diff --git a/runners/genlayer-py-std/src/genlayer/storage/__init__.py b/runners/genlayer-py-std/src/genlayer/storage/__init__.py index 768304977..49c4a66ec 100644 --- a/runners/genlayer-py-std/src/genlayer/storage/__init__.py +++ b/runners/genlayer-py-std/src/genlayer/storage/__init__.py @@ -41,8 +41,6 @@ from ._internal.generate import ( ORIGINAL_INIT_ATTR, - generate_storage, - _known_descs, _storage_build, _BuilderCtx, ) @@ -79,11 +77,8 @@ def cast_slot[T](t: typing.Type[T], manager: Manager, slot: bytes, offset: int, """ Unsafely casts a storage slot to the given type. Use with caution. """ - td = _storage_build(_BuilderCtx.empty(), t) - - instance = td.get(manager.get_store_slot(slot), offset) - - return instance + slt = manager.get_store_slot(slot) + return slt.cast(t, offset) def copy_to_memory[T](val: T, /) -> T: diff --git a/runners/genlayer-py-std/src/genlayer/storage/core.py b/runners/genlayer-py-std/src/genlayer/storage/core.py index 6663ff861..53c88d5f4 100644 --- a/runners/genlayer-py-std/src/genlayer/storage/core.py +++ b/runners/genlayer-py-std/src/genlayer/storage/core.py @@ -105,6 +105,18 @@ def as_int(self) -> u256: """ return int.from_bytes(self.id, 'little', signed=False) + def cast[T](self, t: typing.Type[T], offset: int, /) -> T: + """ + Unsafely casts a storage slot to the given type. Use with caution. + """ + from ._internal.generate import _BuilderCtx, _storage_build + + td = _storage_build(_BuilderCtx.empty(), t) + + instance = td.get(self, offset) + + return instance + def __eq__(self, r: object) -> bool: if not isinstance(r, Slot): return False diff --git a/tests/cases/stable/runners/map_contract_relocated.py b/tests/cases/stable/runners/map_contract_relocated.py index 8e0c5e258..f9faa6a6e 100644 --- a/tests/cases/stable/runners/map_contract_relocated.py +++ b/tests/cases/stable/runners/map_contract_relocated.py @@ -6,17 +6,17 @@ # the relocated contract: a script that maps its OWN runner ("contract") and # checks it received real code. If `map_file("contract")` re-read the (wiped) # default code slot it would get 0 bytes here. -C2 = ( - b'# { "Depends": "py-genlayer:test" }\n' - b'import genlayer as gl\n' - b'from genlayer.vm import map_file\n' - b'class Contract(gl.contract.Contract):\n' - b'\t@gl.public.write\n' - b'\tdef foo(self):\n' - b'\t\tmap_file("contract", "file", "/x")\n' - b'\t\td = open("/x", "rb").read()\n' - b'\t\tprint("ok=" + str(len(d) > 0 and d[:3] == b"# {"))\n' -) +C2 = b"""\ +# { "Depends": "py-genlayer:test" } +import genlayer as gl +from genlayer.vm import map_file +class Contract(gl.contract.Contract): + @gl.public.write + def foo(self): + map_file("contract", "file", "/x") + d = open("/x", "rb").read() + print("ok=" + str(len(d) > 0 and d[:3] == b"# {")) +""" class Contract(gl.contract.Contract): @@ -25,11 +25,10 @@ def __init__(self): # code slot (offset 1) sid = bytes([7]) + bytes(31) s = Root.MANAGER.get_store_slot(sid) - s.write(0, len(C2).to_bytes(4, 'little')) - s.write(4, C2) - Root.get().code_slot = int.from_bytes(sid, 'little') - default = Root.get().slot().indirect(public_abi.root_offsets.CODE) - default.write(0, (0).to_bytes(4, 'little')) + new_code_vla = s.cast(gl.storage.VLA[gl.u8], 0) + new_code_vla.assign(C2) + Root.get().code_slot = s.as_int() + Root.get().code.get().truncate() print('deployed') @gl.public.write From 01b43c365a4c03af7d1e135e4929f7203ae27a7c Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Mon, 22 Jun 2026 20:39:20 +0900 Subject: [PATCH 030/124] =?UTF-8?q?refactor(ci):=20polish=20release-notes?= =?UTF-8?q?=20generator=20(argparse,=20cleaner=20output)=20=E2=99=BB?= =?UTF-8?q?=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch make-relase-notes.py to argparse, strip trailing gitmoji from descriptions, collapse GitHub noreply/bot emails to @handle, and drop squash/PR umbrella subjects when their body bullets are promoted so changes are not double-counted. --- support/ci/make-relase-notes.py | 84 ++++++++++++++++++++++++--------- 1 file changed, 63 insertions(+), 21 deletions(-) diff --git a/support/ci/make-relase-notes.py b/support/ci/make-relase-notes.py index 9d1e460f2..e01480b82 100755 --- a/support/ci/make-relase-notes.py +++ b/support/ci/make-relase-notes.py @@ -1,12 +1,42 @@ #!/usr/bin/env python3 """Generate categorized release notes from conventional commits.""" +import argparse import subprocess import sys import re +import unicodedata from collections import defaultdict from dataclasses import dataclass + +def strip_trailing_emoji(text: str) -> str: + """Drop the trailing gitmoji suffix (and its variation selectors/ZWJ). + + Commit subjects follow ``type(scope): summary ``; the category + heading already conveys the type, so the emoji is redundant noise here. + """ + chars = list(text) + while chars: + c = chars[-1] + if c.isspace() or c in '\ufe0f\u200d' or unicodedata.category(c) in ('So', 'Sk'): + chars.pop() + else: + break + return ''.join(chars).rstrip() + + +NOREPLY_RE = re.compile( + r'(?:\d+\+)?(?P[\w.\[\]-]+)@users\.noreply\.github\.com' +) + + +def format_author(email: str) -> str: + """Collapse GitHub noreply addresses to ``@handle``; keep real emails as-is.""" + m = NOREPLY_RE.fullmatch(email) + return f'@{m.group("handle")}' if m else email + + CATEGORY_LABELS = { 'feat': 'Features', 'fix': 'Bug Fixes', @@ -31,9 +61,11 @@ class CommitEntry: def parse_git_log(rev_range: str) -> list[CommitEntry]: """Run git log and return parsed commit entries. - Each commit's subject line is included directly. Body lines that look - like ``* type: description`` are promoted to top-level entries so they - get categorised on their own (inheriting the commit's author). + Body lines that look like ``* type: description`` are promoted to top-level + entries so they get categorised on their own (inheriting the commit's + author). When a commit has such promoted lines its subject is treated as a + squash/PR umbrella title and dropped — the bullets already carry the real + changes, so keeping the subject would double-count them. """ result = subprocess.run( ['git', 'log', '--pretty=format:%ae%x01%B%x00', rev_range], @@ -50,29 +82,35 @@ def parse_git_log(rev_range: str) -> list[CommitEntry]: lines = [l.strip() for l in body.strip().splitlines() if l.strip()] if not lines: continue - # first line is the subject - entries.append(CommitEntry(lines[0], email)) # body lines starting with * may carry their own conventional prefix - for line in lines[1:]: - cleaned = re.sub(r'^\*\s*', '', line) - if COMMIT_RE.match(cleaned): - entries.append(CommitEntry(cleaned, email)) + promoted = [ + CommitEntry(cleaned, email) + for line in lines[1:] + if COMMIT_RE.match(cleaned := re.sub(r'^\*\s*', '', line)) + ] + if promoted: + entries.extend(promoted) + else: + # no bullets: the subject is the change itself + entries.append(CommitEntry(lines[0], email)) return entries -def categorise(entries: list[CommitEntry]) -> dict[str, list[str]]: +def categorize(entries: list[CommitEntry]) -> dict[str, list[str]]: categories: dict[str, list[str]] = defaultdict(list) for entry in entries: m = COMMIT_RE.match(entry.message) if m: ctype = m.group('type') scope = m.group('scope') - desc = m.group('desc').strip() + desc = strip_trailing_emoji(m.group('desc').strip()) text = f'**{scope}**: {desc}' if scope else desc - text += f' ({entry.email})' + text += f' ({format_author(entry.email)})' categories[ctype].append(text) else: - categories['other'].append(f'{entry.message} ({entry.email})') + categories['other'].append( + f'{strip_trailing_emoji(entry.message)} ({format_author(entry.email)})' + ) return categories @@ -105,19 +143,23 @@ def format_notes(categories: dict[str, list[str]], rev_range: str) -> str: def main() -> None: - if len(sys.argv) < 2: - print(f'Usage: {sys.argv[0]} ', file=sys.stderr) - print(f' e.g. {sys.argv[0]} v0.2.7..v0.2.8', file=sys.stderr) - sys.exit(1) + parser = argparse.ArgumentParser( + description='Generate categorized release notes from conventional commits.', + ) + parser.add_argument( + 'rev_range', + metavar='rev-range', + help='git revision range, e.g. v0.2.7..v0.2.8', + ) + args = parser.parse_args() - rev_range = sys.argv[1] - entries = parse_git_log(rev_range) + entries = parse_git_log(args.rev_range) if not entries: print('No commits found.', file=sys.stderr) sys.exit(1) - categories = categorise(entries) - print(format_notes(categories, rev_range)) + categories = categorize(entries) + print(format_notes(categories, args.rev_range)) if __name__ == '__main__': From 80deb01fdf417ec5eb69d02072a96bdeae6f4c9a Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Mon, 22 Jun 2026 21:18:20 +0900 Subject: [PATCH 031/124] =?UTF-8?q?refactor(executor):=20resolve=20`contra?= =?UTF-8?q?ct`=20runner=20to=20its=20chain=20id=20via=20code=5Fslot=20?= =?UTF-8?q?=E2=99=BB=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/src/host/message.rs | 11 ++++ executor/src/lib.rs | 1 + executor/src/rt/supervisor/actions.rs | 56 +++++++++++-------- executor/src/rt/supervisor/mod.rs | 36 ++++++++++-- executor/src/rt/vm/storage.rs | 8 --- executor/src/runners/mod.rs | 80 ++++++++++++++++++--------- executor/src/wasi/base.rs | 1 + executor/src/wasi/genlayer_sdk.rs | 5 ++ 8 files changed, 136 insertions(+), 62 deletions(-) diff --git a/executor/src/host/message.rs b/executor/src/host/message.rs index d715de013..9d6b046c4 100644 --- a/executor/src/host/message.rs +++ b/executor/src/host/message.rs @@ -40,6 +40,17 @@ impl AccountAddress { #[repr(C)] pub struct SlotID(#[serde_as(as = "Base64")] pub [u8; 32]); +impl genvm_common::calldata::codec::Encode for SlotID { + type Error = W::Error; + + fn encode( + &self, + enc: &mut genvm_common::calldata::Encoder, + ) -> std::result::Result<(), Self::Error> { + enc.push_bytes(&self.0) + } +} + impl SlotID { pub const ZERO: SlotID = SlotID([0; 32]); pub const SIZE: u32 = 32; diff --git a/executor/src/lib.rs b/executor/src/lib.rs index b967d92e6..2a7ffa49f 100644 --- a/executor/src/lib.rs +++ b/executor/src/lib.rs @@ -189,6 +189,7 @@ pub async fn run_with_impl( can_spawn_nondet: permissions.contains("n"), can_register_runners: permissions.contains("u"), state_mode: crate::public_abi::StorageType::Default, + code_slot: crate::SlotID::ZERO, }, message_data: ExtendedMessage { message: entry_data.message, diff --git a/executor/src/rt/supervisor/actions.rs b/executor/src/rt/supervisor/actions.rs index bb75b0406..c837d76c5 100644 --- a/executor/src/rt/supervisor/actions.rs +++ b/executor/src/rt/supervisor/actions.rs @@ -12,6 +12,9 @@ pub struct Ctx<'a, 'b> { pub env: BTreeMap, pub visited: HashSet, pub contract_id: symbol_table::GlobalSymbol, + pub contract_address: calldata::Address, + pub state: public_abi::StorageType, + pub code_slot: crate::SlotID, pub supervisor: &'a rt::supervisor::Supervisor, pub vm: &'b mut rt::vm::VMBase, } @@ -35,9 +38,9 @@ enum ResolvedKind { name: symbol_table::GlobalSymbol, hash: symbol_table::GlobalSymbol, }, - /// The current contract's runner, already preloaded into the cache. - Preloaded, - /// `chain:
::` — code blob read from a storage slot. + /// `chain:
::` — code blob read from a storage slot. The + /// current contract (`contract`) also resolves here, pointing at its own + /// address/state/`code_slot`. Chain { address: calldata::Address, on: public_abi::StorageType, @@ -60,7 +63,9 @@ struct Resolved { /// ([`Ctx`]) and runtime `gl_call`s ([`load_runner`]). fn resolve_runner( supervisor: &rt::supervisor::Supervisor, - contract_id: symbol_table::GlobalSymbol, + contract_address: calldata::Address, + state: public_abi::StorageType, + code_slot: crate::SlotID, id: symbol_table::GlobalSymbol, ) -> anyhow::Result { let Some(parsed) = runners::parse_runner_id(id.as_str()) else { @@ -69,12 +74,8 @@ fn resolve_runner( )); }; - match parsed { - runners::RunnerId::Contract => Ok(Resolved { - id: contract_id, - kind: ResolvedKind::Preloaded, - }), - runners::RunnerId::NameHash { name, hash } => { + match parsed.resolve(contract_address, state, code_slot) { + runners::RunnerId::Builtin { name, hash } => { let hash = if hash.as_str() == "test" || hash.as_str() == "latest" { if !supervisor.shared_data.debug_mode { log_warn!(":test/ :latest runner used in non-debug mode, this is not allowed"); @@ -154,15 +155,6 @@ async fn get_arch( ) .await? } - ResolvedKind::Preloaded => { - cache - .get_or_create( - id, - || async { anyhow::bail!("runner {} is not preloaded", id) }, - limiter, - ) - .await? - } ResolvedKind::Chain { address, on, slot } => { cache .get_or_create( @@ -212,14 +204,16 @@ async fn get_arch( /// contract initialization and runtime `gl_call`s. pub(crate) async fn load_runner( supervisor: &rt::supervisor::Supervisor, - contract_id: symbol_table::GlobalSymbol, + contract_address: calldata::Address, + state: public_abi::StorageType, + code_slot: crate::SlotID, limiter: &rt::memlimiter::Limiter, id: symbol_table::GlobalSymbol, ) -> anyhow::Result<( symbol_table::GlobalSymbol, sync::DArc, )> { - let resolved = resolve_runner(supervisor, contract_id, id)?; + let resolved = resolve_runner(supervisor, contract_address, state, code_slot, id)?; get_arch(supervisor, limiter, resolved).await } @@ -310,12 +304,20 @@ pub(crate) async fn map_runner_file( limiter: &rt::memlimiter::Limiter, contract_address: calldata::Address, state: public_abi::StorageType, + code_slot: crate::SlotID, runner: symbol_table::GlobalSymbol, path_in_runner: &str, path_in_vfs: &str, ) -> anyhow::Result<()> { - let contract_id = runners::get_runner_of_contract(contract_address, state); - let (_id, arch) = load_runner(supervisor, contract_id, limiter, runner).await?; + let (_id, arch) = load_runner( + supervisor, + contract_address, + state, + code_slot, + limiter, + runner, + ) + .await?; map_archive_file( preview1, limiter, @@ -328,7 +330,13 @@ pub(crate) async fn map_runner_file( impl Ctx<'_, '_> { fn resolve_runner(&self, id: symbol_table::GlobalSymbol) -> anyhow::Result { - resolve_runner(self.supervisor, self.contract_id, id) + resolve_runner( + self.supervisor, + self.contract_address, + self.state, + self.code_slot, + id, + ) } async fn get_arch( diff --git a/executor/src/rt/supervisor/mod.rs b/executor/src/rt/supervisor/mod.rs index 913f31a25..45f7e62b2 100644 --- a/executor/src/rt/supervisor/mod.rs +++ b/executor/src/rt/supervisor/mod.rs @@ -408,11 +408,11 @@ pub async fn apply_contract_actions( .conf .state_mode; - let contract_id = runners::get_runner_of_contract(contract_address, contract_state); - let limiter = vm.vm_base.store.data_mut().limits.clone(); - let res = apply_contract_actions_inner(zelf, &mut vm, contract_id, limiter).await; + let res = + apply_contract_actions_inner(zelf, &mut vm, contract_address, contract_state, limiter) + .await; match res { Ok(inst) => Ok(rt::vm::VM { @@ -429,9 +429,32 @@ pub async fn apply_contract_actions( async fn apply_contract_actions_inner( zelf: &std::sync::Arc, vm: &mut rt::vm::VM<()>, - contract_id: GlobalSymbol, + contract_address: calldata::Address, + state: public_abi::StorageType, limiter: rt::memlimiter::Limiter, ) -> anyhow::Result { + let code_slot = vm + .vm_base + .store + .data_mut() + .genlayer_ctx + .genlayer_sdk + .data + .storage + .resolve_code_slot() + .await + .with_context(|| "resolving contract code slot")?; + vm.vm_base + .store + .data_mut() + .genlayer_ctx + .genlayer_sdk + .data + .conf + .code_slot = code_slot; + let contract_id = + GlobalSymbol::from(runners::chain_canonical(contract_address, state, code_slot)); + let contract_major = vm .vm_base .store @@ -467,7 +490,7 @@ async fn apply_contract_actions_inner( .genlayer_sdk .data .storage - .read_code(&limiter) + .read_code_at(code_slot, &limiter) .await .with_context(|| format!("reading contract code for {contract_id}"))?; @@ -489,6 +512,9 @@ async fn apply_contract_actions_inner( env: BTreeMap::new(), visited: HashSet::new(), contract_id, + contract_address, + state, + code_slot, supervisor: zelf, vm: &mut vm.vm_base, }; diff --git a/executor/src/rt/vm/storage.rs b/executor/src/rt/vm/storage.rs index 60cc19387..7164df6fe 100644 --- a/executor/src/rt/vm/storage.rs +++ b/executor/src/rt/vm/storage.rs @@ -407,14 +407,6 @@ impl Storage { Ok(()) } - pub async fn read_code( - &mut self, - limiter: &rt::memlimiter::Limiter, - ) -> anyhow::Result> { - let code_slot = self.resolve_code_slot().await?; - self.read_code_at(code_slot, limiter).await - } - /// Reads the GenVM major version the contract was deployed for, from the /// `major` root field (zero if never written). pub async fn read_major(&mut self) -> anyhow::Result { diff --git a/executor/src/runners/mod.rs b/executor/src/runners/mod.rs index 16cbbfa4f..1c369a7f9 100644 --- a/executor/src/runners/mod.rs +++ b/executor/src/runners/mod.rs @@ -33,8 +33,8 @@ pub fn append_runner_subpath(id: &str, hash: &str, path: &mut std::path::PathBuf /// address, `a`/`f` selects accepted (latest non final) / finalized state and /// `slot` is a `0x`-prefixed 32 byte hex slot id. /// - `custom:` — a runner registered at runtime, looked up by its hash. -pub enum RunnerId { - NameHash { +pub enum RunnerIdUnresolved { + Builtin { name: symbol_table::GlobalSymbol, hash: symbol_table::GlobalSymbol, }, @@ -49,6 +49,49 @@ pub enum RunnerId { }, } +pub enum RunnerId { + Builtin { + name: symbol_table::GlobalSymbol, + hash: symbol_table::GlobalSymbol, + }, + Chain { + address: calldata::Address, + on: crate::public_abi::StorageType, + slot: crate::SlotID, + }, + Custom { + hash: symbol_table::GlobalSymbol, + }, +} + +impl RunnerIdUnresolved { + /// Resolves a parsed runner id against the currently executing contract. + /// + /// The only resolution step is `contract` → the `chain:` id pointing at this + /// contract's own code (its address, state and resolved `code_slot`), so the + /// current contract is loaded through the exact same path as any other + /// `chain:` runner. + pub fn resolve( + self, + contract_address: calldata::Address, + state: crate::public_abi::StorageType, + code_slot: crate::SlotID, + ) -> RunnerId { + match self { + RunnerIdUnresolved::Contract => RunnerId::Chain { + address: contract_address, + on: state, + slot: code_slot, + }, + RunnerIdUnresolved::Builtin { name, hash } => RunnerId::Builtin { name, hash }, + RunnerIdUnresolved::Chain { address, on, slot } => { + RunnerId::Chain { address, on, slot } + } + RunnerIdUnresolved::Custom { hash } => RunnerId::Custom { hash }, + } + } +} + fn is_hash_char(c: char) -> bool { c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '=' } @@ -63,9 +106,9 @@ fn parse_hex_fixed(s: &str) -> Option<[u8; N]> { Some(out) } -pub fn parse_runner_id(id: &str) -> Option { +pub fn parse_runner_id(id: &str) -> Option { if id == "contract" { - return Some(RunnerId::Contract); + return Some(RunnerIdUnresolved::Contract); } if let Some(rest) = id.strip_prefix("chain:") { @@ -85,14 +128,14 @@ pub fn parse_runner_id(id: &str) -> Option { }; let slot = crate::SlotID::from_bytes(parse_hex_fixed::<32>(slot)?); - return Some(RunnerId::Chain { address, on, slot }); + return Some(RunnerIdUnresolved::Chain { address, on, slot }); } if let Some(rest) = id.strip_prefix("custom:") { if rest.is_empty() || !rest.chars().all(is_hash_char) { return None; } - return Some(RunnerId::Custom { + return Some(RunnerIdUnresolved::Custom { hash: symbol_table::GlobalSymbol::new(rest), }); } @@ -110,7 +153,7 @@ pub fn parse_runner_id(id: &str) -> Option { if !hash.chars().all(is_hash_char) { return None; } - Some(RunnerId::NameHash { + Some(RunnerIdUnresolved::Builtin { name: symbol_table::GlobalSymbol::new(name), hash: symbol_table::GlobalSymbol::new(hash), }) @@ -151,19 +194,6 @@ pub fn custom_runner_id(hash: symbol_table::GlobalSymbol) -> symbol_table::Globa symbol_table::GlobalSymbol::from(id) } -pub fn get_runner_of_contract( - address: calldata::Address, - state: crate::public_abi::StorageType, -) -> symbol_table::GlobalSymbol { - // This is only the cache key for the contract's runner archive; it always - // uses the default `code` slot, even when the contract set a `code_slot` - // redirect. That is fine: the key only needs to be unique per (address, - // state), and the actual code is read by `Storage::read_code`, which honors - // `code_slot`. The key is not a code location. - let slot = crate::SlotID::ZERO.indirection(crate::public_abi::root_offsets::CODE); - symbol_table::GlobalSymbol::from(chain_canonical(address, state, slot)) -} - pub struct ArchiveCache { pub(super) id: symbol_table::GlobalSymbol, pub(super) files: Archive, @@ -273,25 +303,25 @@ mod tests { fn parse_runner_id_forms() { assert!(matches!( parse_runner_id("contract"), - Some(RunnerId::Contract) + Some(RunnerIdUnresolved::Contract) )); assert!(matches!( parse_runner_id("py-genlayer:test"), - Some(RunnerId::NameHash { .. }) + Some(RunnerIdUnresolved::Builtin { .. }) )); assert!(matches!( parse_runner_id("custom:deadbeef"), - Some(RunnerId::Custom { .. }) + Some(RunnerIdUnresolved::Custom { .. }) )); match parse_runner_id(&format!("chain:{}:f:{}", addr40(), slot64())) { - Some(RunnerId::Chain { on, .. }) => { + Some(RunnerIdUnresolved::Chain { on, .. }) => { assert_eq!(on, crate::public_abi::StorageType::LatestFinal) } _ => panic!("expected a chain runner id"), } match parse_runner_id(&format!("chain:{}:a:{}", addr40(), slot64())) { - Some(RunnerId::Chain { on, .. }) => { + Some(RunnerIdUnresolved::Chain { on, .. }) => { assert_eq!(on, crate::public_abi::StorageType::LatestNonFinal) } _ => panic!("expected a chain runner id"), diff --git a/executor/src/wasi/base.rs b/executor/src/wasi/base.rs index dfe1dad84..ca395e322 100644 --- a/executor/src/wasi/base.rs +++ b/executor/src/wasi/base.rs @@ -13,6 +13,7 @@ pub struct Config { pub can_call_others: bool, pub can_register_runners: bool, pub state_mode: public_abi::StorageType, + pub code_slot: crate::SlotID, } impl Config { diff --git a/executor/src/wasi/genlayer_sdk.rs b/executor/src/wasi/genlayer_sdk.rs index e3311b777..401dff27c 100644 --- a/executor/src/wasi/genlayer_sdk.rs +++ b/executor/src/wasi/genlayer_sdk.rs @@ -721,6 +721,7 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { can_send_messages: my_conf.can_send_messages, can_register_runners: my_conf.can_register_runners, state_mode: state, + code_slot: crate::SlotID::ZERO, }, message_data: ExtendedMessage { message: genlayer_sdk::abi::entry::MessageData { @@ -1600,6 +1601,7 @@ impl ContextVFS<'_> { let limiter = supervisor.limiter.get(is_det); let contract_address = self.context.data.message_data.message.contract_address; let state = self.context.data.conf.state_mode; + let code_slot = self.context.data.conf.code_slot; rt::supervisor::actions::map_runner_file( &supervisor, @@ -1607,6 +1609,7 @@ impl ContextVFS<'_> { limiter, contract_address, state, + code_slot, symbol_table::GlobalSymbol::from(runner), &path_in_runner, &path_in_vfs, @@ -1786,6 +1789,7 @@ impl ContextVFS<'_> { can_send_messages: false, can_register_runners: false, state_mode: public_abi::StorageType::Default, + code_slot: crate::SlotID::ZERO, }, message_data, supervisor: supervisor.clone(), @@ -1876,6 +1880,7 @@ impl ContextVFS<'_> { can_send_messages: zelf_conf.can_send_messages & allow_send_messages, can_register_runners: zelf_conf.can_register_runners & allow_register_runners, state_mode: zelf_conf.state_mode, + code_slot: crate::SlotID::ZERO, }, message_data, supervisor: supervisor.clone(), From 8c70d9f9de82f1542915e343d42134f7174d634e Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Mon, 22 Jun 2026 21:38:25 +0900 Subject: [PATCH 032/124] =?UTF-8?q?refactor(executor):=20add=20RunnerId::c?= =?UTF-8?q?anonical=5Fid,=20inline=20chain=5Fcanonical=20=E2=99=BB?= =?UTF-8?q?=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/src/rt/supervisor/actions.rs | 17 ++---- executor/src/rt/supervisor/mod.rs | 8 ++- executor/src/runners/mod.rs | 85 +++++++++++++++------------ 3 files changed, 58 insertions(+), 52 deletions(-) diff --git a/executor/src/rt/supervisor/actions.rs b/executor/src/rt/supervisor/actions.rs index c837d76c5..66eee99f0 100644 --- a/executor/src/rt/supervisor/actions.rs +++ b/executor/src/rt/supervisor/actions.rs @@ -5,7 +5,6 @@ use crate::{caching, public_abi, rt, runners}; use anyhow::Context as _; use genlayer_sdk::abi; use genvm_common::*; -use symbol_table::GlobalSymbol; use wiggle::error::Context as _; pub struct Ctx<'a, 'b> { @@ -75,7 +74,7 @@ fn resolve_runner( }; match parsed.resolve(contract_address, state, code_slot) { - runners::RunnerId::Builtin { name, hash } => { + runners::Id::Builtin { name, hash } => { let hash = if hash.as_str() == "test" || hash.as_str() == "latest" { if !supervisor.shared_data.debug_mode { log_warn!(":test/ :latest runner used in non-debug mode, this is not allowed"); @@ -99,21 +98,17 @@ fn resolve_runner( anyhow::bail!("runner {}:{} not found", name, hash); } - let mut canonical = name.as_str().to_owned(); - canonical.push(':'); - canonical.push_str(hash.as_str()); - Ok(Resolved { - id: GlobalSymbol::new(canonical), + id: runners::Id::Builtin { name, hash }.canonical(), kind: ResolvedKind::Disk { name, hash }, }) } - runners::RunnerId::Chain { address, on, slot } => Ok(Resolved { - id: GlobalSymbol::from(runners::chain_canonical(address, on, slot)), + runners::Id::Chain { address, on, slot } => Ok(Resolved { + id: runners::Id::Chain { address, on, slot }.canonical(), kind: ResolvedKind::Chain { address, on, slot }, }), - runners::RunnerId::Custom { hash } => Ok(Resolved { - id: runners::custom_runner_id(hash), + runners::Id::Custom { hash } => Ok(Resolved { + id: runners::Id::Custom { hash }.canonical(), kind: ResolvedKind::Custom { hash }, }), } diff --git a/executor/src/rt/supervisor/mod.rs b/executor/src/rt/supervisor/mod.rs index 45f7e62b2..942b9f4ce 100644 --- a/executor/src/rt/supervisor/mod.rs +++ b/executor/src/rt/supervisor/mod.rs @@ -452,8 +452,12 @@ async fn apply_contract_actions_inner( .data .conf .code_slot = code_slot; - let contract_id = - GlobalSymbol::from(runners::chain_canonical(contract_address, state, code_slot)); + let contract_id = runners::Id::Chain { + address: contract_address, + on: state, + slot: code_slot, + } + .canonical(); let contract_major = vm .vm_base diff --git a/executor/src/runners/mod.rs b/executor/src/runners/mod.rs index 1c369a7f9..f028caaca 100644 --- a/executor/src/runners/mod.rs +++ b/executor/src/runners/mod.rs @@ -33,7 +33,7 @@ pub fn append_runner_subpath(id: &str, hash: &str, path: &mut std::path::PathBuf /// address, `a`/`f` selects accepted (latest non final) / finalized state and /// `slot` is a `0x`-prefixed 32 byte hex slot id. /// - `custom:` — a runner registered at runtime, looked up by its hash. -pub enum RunnerIdUnresolved { +pub enum IdUnresolved { Builtin { name: symbol_table::GlobalSymbol, hash: symbol_table::GlobalSymbol, @@ -49,7 +49,7 @@ pub enum RunnerIdUnresolved { }, } -pub enum RunnerId { +pub enum Id { Builtin { name: symbol_table::GlobalSymbol, hash: symbol_table::GlobalSymbol, @@ -64,7 +64,7 @@ pub enum RunnerId { }, } -impl RunnerIdUnresolved { +impl IdUnresolved { /// Resolves a parsed runner id against the currently executing contract. /// /// The only resolution step is `contract` → the `chain:` id pointing at this @@ -76,18 +76,45 @@ impl RunnerIdUnresolved { contract_address: calldata::Address, state: crate::public_abi::StorageType, code_slot: crate::SlotID, - ) -> RunnerId { + ) -> Id { match self { - RunnerIdUnresolved::Contract => RunnerId::Chain { + IdUnresolved::Contract => Id::Chain { address: contract_address, on: state, slot: code_slot, }, - RunnerIdUnresolved::Builtin { name, hash } => RunnerId::Builtin { name, hash }, - RunnerIdUnresolved::Chain { address, on, slot } => { - RunnerId::Chain { address, on, slot } + IdUnresolved::Builtin { name, hash } => Id::Builtin { name, hash }, + IdUnresolved::Chain { address, on, slot } => Id::Chain { address, on, slot }, + IdUnresolved::Custom { hash } => Id::Custom { hash }, + } + } +} + +impl Id { + /// The canonical textual runner id, used as the archive cache key. Two ids + /// that resolve to the same `(name, hash)` / `(address, state, slot)` / hash + /// produce the same symbol (e.g. `contract` and an explicit self `chain:`). + pub fn canonical(&self) -> symbol_table::GlobalSymbol { + match self { + Id::Builtin { name, hash } => { + let mut id = name.as_str().to_owned(); + id.push(':'); + id.push_str(hash.as_str()); + symbol_table::GlobalSymbol::from(id) + } + Id::Chain { address, on, slot } => { + let on = match *on { + crate::public_abi::StorageType::LatestFinal => 'f', + _ => 'a', + }; + symbol_table::GlobalSymbol::from(format!( + "chain:0x{}:{}:0x{}", + hex::encode(address.raw()), + on, + hex::encode(slot.raw()) + )) } - RunnerIdUnresolved::Custom { hash } => RunnerId::Custom { hash }, + Id::Custom { hash } => custom_runner_id(*hash), } } } @@ -106,9 +133,9 @@ fn parse_hex_fixed(s: &str) -> Option<[u8; N]> { Some(out) } -pub fn parse_runner_id(id: &str) -> Option { +pub fn parse_runner_id(id: &str) -> Option { if id == "contract" { - return Some(RunnerIdUnresolved::Contract); + return Some(IdUnresolved::Contract); } if let Some(rest) = id.strip_prefix("chain:") { @@ -128,14 +155,14 @@ pub fn parse_runner_id(id: &str) -> Option { }; let slot = crate::SlotID::from_bytes(parse_hex_fixed::<32>(slot)?); - return Some(RunnerIdUnresolved::Chain { address, on, slot }); + return Some(IdUnresolved::Chain { address, on, slot }); } if let Some(rest) = id.strip_prefix("custom:") { if rest.is_empty() || !rest.chars().all(is_hash_char) { return None; } - return Some(RunnerIdUnresolved::Custom { + return Some(IdUnresolved::Custom { hash: symbol_table::GlobalSymbol::new(rest), }); } @@ -153,32 +180,12 @@ pub fn parse_runner_id(id: &str) -> Option { if !hash.chars().all(is_hash_char) { return None; } - Some(RunnerIdUnresolved::Builtin { + Some(IdUnresolved::Builtin { name: symbol_table::GlobalSymbol::new(name), hash: symbol_table::GlobalSymbol::new(hash), }) } -/// Canonical textual form of a [`RunnerId::Chain`]. Used as the cache key so -/// that an explicit `chain:` reference and the current `contract` resolve to the -/// same entry when they point at the same address/state/slot. -pub fn chain_canonical( - address: calldata::Address, - on: crate::public_abi::StorageType, - slot: crate::SlotID, -) -> String { - let on = match on { - crate::public_abi::StorageType::LatestFinal => 'f', - _ => 'a', - }; - format!( - "chain:0x{}:{}:0x{}", - hex::encode(address.raw()), - on, - hex::encode(slot.raw()) - ) -} - /// Derives the hash component of a `custom:` runner id from its code. pub fn custom_runner_hash(code: &[u8]) -> symbol_table::GlobalSymbol { use sha3::Digest as _; @@ -303,25 +310,25 @@ mod tests { fn parse_runner_id_forms() { assert!(matches!( parse_runner_id("contract"), - Some(RunnerIdUnresolved::Contract) + Some(IdUnresolved::Contract) )); assert!(matches!( parse_runner_id("py-genlayer:test"), - Some(RunnerIdUnresolved::Builtin { .. }) + Some(IdUnresolved::Builtin { .. }) )); assert!(matches!( parse_runner_id("custom:deadbeef"), - Some(RunnerIdUnresolved::Custom { .. }) + Some(IdUnresolved::Custom { .. }) )); match parse_runner_id(&format!("chain:{}:f:{}", addr40(), slot64())) { - Some(RunnerIdUnresolved::Chain { on, .. }) => { + Some(IdUnresolved::Chain { on, .. }) => { assert_eq!(on, crate::public_abi::StorageType::LatestFinal) } _ => panic!("expected a chain runner id"), } match parse_runner_id(&format!("chain:{}:a:{}", addr40(), slot64())) { - Some(RunnerIdUnresolved::Chain { on, .. }) => { + Some(IdUnresolved::Chain { on, .. }) => { assert_eq!(on, crate::public_abi::StorageType::LatestNonFinal) } _ => panic!("expected a chain runner id"), From dce35197cd062af9db2996372d27ef1a990f44c2 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Mon, 22 Jun 2026 22:31:57 +0900 Subject: [PATCH 033/124] =?UTF-8?q?feat(executor):=20add=20gvm32=20Crockfo?= =?UTF-8?q?rd=20Base32=20codec=20(rust/python/nix)=20+=20spec=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spec/04-contract-interface/06-gvm32.rst | 68 ++++++++++++++++ .../src/spec/04-contract-interface/index.rst | 1 + executor/crates/sdk-rs/src/gvm32.rs | 63 +++++++++++++++ executor/crates/sdk-rs/src/lib.rs | 1 + executor/crates/sdk-rs/tests/gvm32.rs | 67 ++++++++++++++++ runners/genlayer-py-std/src/genlayer/gvm32.py | 78 +++++++++++++++++++ runners/genlayer-py-std/tests/test_gvm32.py | 41 ++++++++++ runners/support/gvm32.nix | 55 +++++++++++++ 8 files changed, 374 insertions(+) create mode 100644 doc/website/src/spec/04-contract-interface/06-gvm32.rst create mode 100644 executor/crates/sdk-rs/src/gvm32.rs create mode 100644 executor/crates/sdk-rs/tests/gvm32.rs create mode 100644 runners/genlayer-py-std/src/genlayer/gvm32.py create mode 100644 runners/genlayer-py-std/tests/test_gvm32.py create mode 100644 runners/support/gvm32.nix diff --git a/doc/website/src/spec/04-contract-interface/06-gvm32.rst b/doc/website/src/spec/04-contract-interface/06-gvm32.rst new file mode 100644 index 000000000..dd658944a --- /dev/null +++ b/doc/website/src/spec/04-contract-interface/06-gvm32.rst @@ -0,0 +1,68 @@ +GVM32 (Base32) +============== + +:term:`GenVM` encodes hash-like binary values — runner content hashes, +``custom:`` ids and :term:`SlotID`\s — as text using **GVM32**, a variant +of `Crockford's Base32 `_. + +Alphabet +-------- + +The 32-symbol alphabet is:: + + 0123456789abcdefghjkmnpqrstvwxyz + +That is, the digits ``0`` -- ``9`` followed by the lowercase letters ``a`` -- ``z`` with +``i``, ``l``, ``o`` and ``u`` removed. The symbol at index ``v`` (``0 <= v < 32``) +encodes the 5-bit value ``v``. + +Encoding +-------- + +The input is treated as a big-endian bit stream (the most significant bit of the +first octet first). It is split into groups of 5 bits, each group emitted as the +alphabet symbol for its value. If the final group has fewer than 5 bits it is +padded on the **low** side with zero bits. There is **no** ``=`` padding. + +An input of ``N`` octets therefore produces ``ceil(N * 8 / 5)`` symbols. The +canonical (and default) encoding is **lowercase**. + +.. code-block:: python + + ALPHABET = '0123456789abcdefghjkmnpqrstvwxyz' + + def encode(data: bytes) -> str: + out = [] + value = bits = 0 + for byte in data: + value = (value << 8) | byte + bits += 8 + while bits >= 5: + bits -= 5 + out.append(ALPHABET[(value >> bits) & 0x1F]) + if bits > 0: + out.append(ALPHABET[(value << (5 - bits)) & 0x1F]) + return ''.join(out) + +Decoding +-------- + +Decoding is **case-insensitive**. Following Crockford's rules, the letters ``i`` +and ``l`` (and ``I``, ``L``) are read as ``1`` and ``o`` (and ``O``) as ``0``. +Hyphens (``-``) may appear for readability and are ignored. Any other character +makes the string invalid. + +The 5-bit values are concatenated big-endian; every full group of 8 bits is one +output octet. A well-formed string has its trailing (sub-octet) bits all zero — +a decoder must reject a string whose leftover bits are non-zero. + +Usage +----- + +- **Runner content hashes** — the ``hash`` component of a ``name:hash`` runner id + (see :doc:`../02-execution-environment/04-runners`) is the GVM32 encoding of the + runner archive's hash. +- **Custom runner ids** — ``custom:`` where ```` is the GVM32 encoding + of the SHA3-256 of the registered code. +- **Slot ids** — a :term:`SlotID` is rendered in GVM32, including the ```` + component of a ``chain:
::`` runner id. diff --git a/doc/website/src/spec/04-contract-interface/index.rst b/doc/website/src/spec/04-contract-interface/index.rst index 5d468c7fe..8ef110031 100644 --- a/doc/website/src/spec/04-contract-interface/index.rst +++ b/doc/website/src/spec/04-contract-interface/index.rst @@ -11,3 +11,4 @@ Interfaces and protocols for contract interaction and data management. 03-storage 04-upgradability 05-execution-flow + 06-gvm32 diff --git a/executor/crates/sdk-rs/src/gvm32.rs b/executor/crates/sdk-rs/src/gvm32.rs new file mode 100644 index 000000000..59bddd178 --- /dev/null +++ b/executor/crates/sdk-rs/src/gvm32.rs @@ -0,0 +1,63 @@ +//! # GenVM base32 encoder/decoder +//! +//! Uses [Crockford's Base32](https://www.crockford.com/base32.html): the +//! alphabet `0123456789abcdefghjkmnpqrstvwxyz` (excludes `i`, `l`, `o`, `u`), +//! no padding, big-endian bit packing. Encoding is lowercase by default; +//! decoding is case-insensitive, treats `i`/`l` as `1` and `o` as `0`, and +//! ignores `-`. Used for encoding hashes. + +const ALPHABET: &[u8] = b"0123456789abcdefghjkmnpqrstvwxyz"; + +/// Encodes a byte slice as a Crockford Base32 string (uppercase, no padding). +pub fn encode(bytes: &[u8]) -> String { + let mut out = String::with_capacity(bytes.len() * 8 / 5 + 1); + let mut value: u32 = 0; + let mut bits: u32 = 0; + for &b in bytes { + value = (value << 8) | b as u32; + bits += 8; + while bits >= 5 { + bits -= 5; + out.push(ALPHABET[((value >> bits) & 0x1f) as usize] as char); + } + value &= (1 << bits) - 1; + } + if bits > 0 { + out.push(ALPHABET[((value << (5 - bits)) & 0x1f) as usize] as char); + } + out +} + +fn decode_char(c: u8) -> Option { + let c = match c.to_ascii_lowercase() { + b'o' => b'0', + b'i' | b'l' => b'1', + other => other, + }; + ALPHABET.iter().position(|&b| b == c).map(|p| p as u8) +} + +/// Decodes a Crockford Base32 string. Case-insensitive; `i`/`l` are read as `1`, +/// `o` as `0` and `-` is ignored. Returns `None` on an invalid character or +/// non-zero trailing padding bits. +pub fn decode(s: &str) -> Option> { + let mut out = Vec::with_capacity(s.len() * 5 / 8); + let mut value: u32 = 0; + let mut bits: u32 = 0; + for &c in s.as_bytes() { + if c == b'-' { + continue; + } + value = (value << 5) | decode_char(c)? as u32; + bits += 5; + if bits >= 8 { + bits -= 8; + out.push((value >> bits) as u8); + value &= (1 << bits) - 1; + } + } + if value != 0 { + return None; + } + Some(out) +} diff --git a/executor/crates/sdk-rs/src/lib.rs b/executor/crates/sdk-rs/src/lib.rs index ac89b1cc2..eb6236d62 100644 --- a/executor/crates/sdk-rs/src/lib.rs +++ b/executor/crates/sdk-rs/src/lib.rs @@ -1,4 +1,5 @@ pub mod abi; +pub mod gvm32; pub use genlayer_calldata as calldata; #[cfg(feature = "storage")] diff --git a/executor/crates/sdk-rs/tests/gvm32.rs b/executor/crates/sdk-rs/tests/gvm32.rs new file mode 100644 index 000000000..52c877c6e --- /dev/null +++ b/executor/crates/sdk-rs/tests/gvm32.rs @@ -0,0 +1,67 @@ +use genlayer_sdk::gvm32; + +#[test] +fn round_trip() { + let cases = [ + // hex, gvm32 (Crockford Base32, lowercase) + ( + "ab335240fd942ab8191c5e628cd4ff3903c577bda961fb75df08e0303a00527b", + "ncsn4g7xjgnbg68wbsh8sn7z741waxxxn5gzpxez13g30eg0a9xg", + ), + ( + "47b2d8f260c2d48116044bc43fe3de0f", + "8ysdhwk0rba825g49f23zryy1w", + ), + ( + "1f74d74729abdc08f4f84e8f7f8c808c8ed92ee5", + "3xtdehs9nfe0hx7r9t7qz340hj7djbq5", + ), + ( + "a315ab26a0c4829321730c44a26f4497f7da0631402669caa4e24bdcd9db7c87", + "mcatp9n0rj1968bk1h2a4vt4jzvxm1hh80k6kjn4w95xspevfj3g", + ), + ( + "296a445bfa5e1990af299ec74582468ab7a77e495861691ff79ab21234e514b64fc72b294d7305ecdd0febaa13b1bc1a3f359a711bb93dfb2b82804c64354dab", + "55n48pztbrcs1bs9kv3mb0j6havtezj9b1gpj7zqkas14d752jv4zhsb556q61fcvm7yqagkp6y1mfsnk9rhqe9xzcnr502ccgtmvar", + ), + ( + "99a2da84cec54d17325bcee0a079669c1b15eb7ead32246514b75b97862f1e00", + "k6hdn16ern6hecjvsvga0yb6kgdhbtvynms28s8mpxdsf1hf3r00", + ), + ]; + + for (hex, b32) in cases { + let bytes = hex::decode(hex).unwrap(); + assert_eq!(gvm32::encode(&bytes), b32, "encode {hex}"); + assert_eq!(gvm32::decode(b32).unwrap(), bytes, "decode {b32}"); + } +} + +#[test] +fn empty() { + assert_eq!(gvm32::encode(&[]), ""); + assert_eq!(gvm32::decode("").unwrap(), Vec::::new()); +} + +#[test] +fn case_insensitive_and_aliases() { + let bytes = hex::decode("47b2d8f260c2d48116044bc43fe3de0f").unwrap(); + let canonical = "8ysdhwk0rba825g49f23zryy1w"; + // uppercase decodes the same + assert_eq!(gvm32::decode(&canonical.to_uppercase()).unwrap(), bytes); + // hyphens are ignored + assert_eq!( + gvm32::decode("8ysd-hwk0-rba8-25g4-9f23-zryy-1w").unwrap(), + bytes + ); + // crockford aliases: i/l -> 1, o -> 0 + assert_eq!(gvm32::decode("OoIiLl"), gvm32::decode("001111")); +} + +#[test] +fn rejects_invalid() { + // `u` is not in the alphabet and is not an alias + assert_eq!(gvm32::decode("u"), None); + // non-zero trailing padding bits + assert_eq!(gvm32::decode("01"), None); +} diff --git a/runners/genlayer-py-std/src/genlayer/gvm32.py b/runners/genlayer-py-std/src/genlayer/gvm32.py new file mode 100644 index 000000000..e0e7f9709 --- /dev/null +++ b/runners/genlayer-py-std/src/genlayer/gvm32.py @@ -0,0 +1,78 @@ +""" +GenVM base32 encoder/decoder. + +Uses `Crockford's Base32 `_: the alphabet +``0123456789abcdefghjkmnpqrstvwxyz`` (excludes ``i``, ``l``, ``o``, ``u``), no +padding, big-endian bit packing. Encoding is lowercase by default; decoding is +case-insensitive, treats ``i``/``l`` as ``1`` and ``o`` as ``0``, and ignores +``-``. Used to encode hashes (such as runner ids). Mirrors the Rust +``genlayer_sdk::gvm32`` implementation. +""" + +__all__ = ('encode', 'decode') + +import collections.abc + +_ALPHABET = '0123456789abcdefghjkmnpqrstvwxyz' + + +def encode(data: collections.abc.Buffer) -> str: + """ + Encode a byte buffer to its Crockford Base32 string (uppercase, no padding). + + :param data: bytes to encode + :returns: the base32-encoded string + """ + out: list[str] = [] + value = 0 + bits = 0 + for byte in bytes(data): + value = (value << 8) | byte + bits += 8 + while bits >= 5: + bits -= 5 + out.append(_ALPHABET[(value >> bits) & 0x1F]) + if bits > 0: + out.append(_ALPHABET[(value << (5 - bits)) & 0x1F]) + return ''.join(out) + + +def _decode_char(ch: str) -> int | None: + c = ch.lower() + if c == 'o': + c = '0' + elif c in ('i', 'l'): + c = '1' + idx = _ALPHABET.find(c) + return idx if idx >= 0 else None + + +def decode(s: str) -> bytes | None: + """ + Decode a Crockford Base32 string back to bytes. + + Case-insensitive; ``i``/``l`` are read as ``1``, ``o`` as ``0`` and ``-`` is + ignored. + + :param s: base32 string + :returns: the decoded bytes, or ``None`` if ``s`` contains an invalid + character or has non-zero trailing padding bits + """ + out = bytearray() + value = 0 + bits = 0 + for ch in s: + if ch == '-': + continue + digit = _decode_char(ch) + if digit is None: + return None + value = (value << 5) | digit + bits += 5 + if bits >= 8: + bits -= 8 + out.append((value >> bits) & 0xFF) + # any leftover bits are padding and must be zero + if value & ((1 << bits) - 1): + return None + return bytes(out) diff --git a/runners/genlayer-py-std/tests/test_gvm32.py b/runners/genlayer-py-std/tests/test_gvm32.py new file mode 100644 index 000000000..a5b800732 --- /dev/null +++ b/runners/genlayer-py-std/tests/test_gvm32.py @@ -0,0 +1,41 @@ +from genlayer.gvm32 import encode, decode + +# hex, gvm32 (Crockford Base32, lowercase) — shared with executor/crates/sdk-rs/tests/gvm32.rs +CASES = [ + ( + 'ab335240fd942ab8191c5e628cd4ff3903c577bda961fb75df08e0303a00527b', + 'ncsn4g7xjgnbg68wbsh8sn7z741waxxxn5gzpxez13g30eg0a9xg', + ), + ('47b2d8f260c2d48116044bc43fe3de0f', '8ysdhwk0rba825g49f23zryy1w'), + ('1f74d74729abdc08f4f84e8f7f8c808c8ed92ee5', '3xtdehs9nfe0hx7r9t7qz340hj7djbq5'), + ( + '99a2da84cec54d17325bcee0a079669c1b15eb7ead32246514b75b97862f1e00', + 'k6hdn16ern6hecjvsvga0yb6kgdhbtvynms28s8mpxdsf1hf3r00', + ), +] + + +def test_round_trip(): + for hexs, b32 in CASES: + raw = bytes.fromhex(hexs) + assert encode(raw) == b32 + assert decode(b32) == raw + + +def test_empty(): + assert encode(b'') == '' + assert decode('') == b'' + + +def test_case_insensitive_and_aliases(): + raw = bytes.fromhex('47b2d8f260c2d48116044bc43fe3de0f') + canonical = '8ysdhwk0rba825g49f23zryy1w' + assert decode(canonical.upper()) == raw + assert decode('8ysd-hwk0-rba8-25g4-9f23-zryy-1w') == raw + # crockford aliases: i/l -> 1, o -> 0 + assert decode('ooiill') == decode('001111') + + +def test_rejects_invalid(): + assert decode('u') is None # not in alphabet, not an alias + assert decode('01') is None # non-zero trailing padding bits diff --git a/runners/support/gvm32.nix b/runners/support/gvm32.nix new file mode 100644 index 000000000..804f8f35e --- /dev/null +++ b/runners/support/gvm32.nix @@ -0,0 +1,55 @@ +# GenVM base32 (Crockford's Base32, lowercase) encoder. +# +# Mirrors executor/crates/sdk-rs/src/gvm32.rs and +# runners/genlayer-py-std/src/genlayer/gvm32.py. Used to derive runner content +# hash ids. Implemented per output symbol (not by accumulating the whole value) +# so it never overflows Nix's 64-bit integers, even for long hashes. +{ lib }: +let + alphabet = lib.stringToCharacters "0123456789abcdefghjkmnpqrstvwxyz"; + + # Nix `/` is integer division for ints; there is no `%` operator. + mod = a: b: a - b * (a / b); + pow2 = n: builtins.foldl' (acc: _: acc * 2) 1 (lib.range 1 n); + + hexValues = { + "0" = 0; "1" = 1; "2" = 2; "3" = 3; "4" = 4; "5" = 5; "6" = 6; "7" = 7; + "8" = 8; "9" = 9; "a" = 10; "b" = 11; "c" = 12; "d" = 13; "e" = 14; + "f" = 15; "A" = 10; "B" = 11; "C" = 12; "D" = 13; "E" = 14; "F" = 15; + }; + + # hex string -> list of byte integers + hexToBytes = hex: + let + chars = lib.stringToCharacters hex; + n = (builtins.length chars) / 2; + in + builtins.genList + (i: hexValues.${builtins.elemAt chars (i * 2)} * 16 + + hexValues.${builtins.elemAt chars (i * 2 + 1)}) + n; + + # list of byte integers -> Crockford Base32 string + encode = bytes: + let + len = builtins.length bytes; + byteAt = i: if i < len then builtins.elemAt bytes i else 0; + nsym = (len * 8 + 4) / 5; # ceil(len * 8 / 5) + symAt = k: + let + b = k * 5; + i = b / 8; + j = mod b 8; + # 16-bit big-endian window over bytes[i], bytes[i+1] + window = byteAt i * 256 + byteAt (i + 1); + v = mod (window / (pow2 (11 - j))) 32; + in + builtins.elemAt alphabet v; + in + lib.concatStrings (builtins.genList symAt nsym); + + encodeHex = hex: encode (hexToBytes hex); +in +{ + inherit encode encodeHex; +} From 6ce3f2f78b8f3aa8258105f6edd35b1a1f6faf07 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Mon, 22 Jun 2026 22:32:12 +0900 Subject: [PATCH 034/124] =?UTF-8?q?feat(executor):=20encode=20built-in/cus?= =?UTF-8?q?tom=20runner=20hashes=20and=20slot=20ids=20with=20gvm32=20?= =?UTF-8?q?=E2=99=BB=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/schemas/runners.json | 4 +-- .../03-wasi_genlayer_sdk/02-gl_call.rst | 7 +++-- .../02-execution-environment/04-runners.rst | 29 +++++------------- executor/src/host/message.rs | 6 ++++ executor/src/runners/mod.rs | 13 ++++---- runners/support/default.nix | 3 +- support/runner-script.py | 30 +++++++++---------- .../stable/runners/register-runner.0.stdout | 2 +- .../stable/runners/register_loop.0.stdout | 2 +- 9 files changed, 45 insertions(+), 51 deletions(-) diff --git a/doc/schemas/runners.json b/doc/schemas/runners.json index ac3571235..12e474914 100644 --- a/doc/schemas/runners.json +++ b/doc/schemas/runners.json @@ -24,8 +24,8 @@ "description": "the runner of the contract that is currently being executed" }, { - "pattern": "^chain:0x[0-9a-fA-F]{40}:[af]:0x[0-9a-fA-F]{64}$", - "description": "`chain:
::` — code blob read from a `0x` 20 byte address at a `0x` 32 byte slot, `a`=accepted / `f`=finalized" + "pattern": "^chain:0x[0-9a-fA-F]{40}:[af]:[0-9abcdefghjkmnpqrstvwxyz]{52}$", + "description": "`chain:
::` — code blob read from a `0x` 20 byte address at a GVM32-encoded 32 byte slot, `a`=accepted / `f`=finalized" }, { "pattern": "^custom:[a-zA-Z0-9_=-]+$", diff --git a/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst b/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst index be1c99009..5ef87f2da 100644 --- a/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst +++ b/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst @@ -192,9 +192,10 @@ Creates isolated VM instance. See :ref:`gvm-permissions` for permission inherita -------------------------- Registers a runner archive at runtime, making it available under the -``custom:`` runner id. The ```` is -derived from the supplied ``code`` and the parsed archive is charged against the -memory limit. Returns the resulting runner id (calldata-encoded string). +``custom:`` runner id. The ```` is the SHA3-256 of the supplied +``code`` encoded with :doc:`../../04-contract-interface/06-gvm32`, and the parsed +archive is charged against the memory limit. Returns the resulting runner id +(calldata-encoded string). Payload ~~~~~~~ diff --git a/doc/website/src/spec/02-execution-environment/04-runners.rst b/doc/website/src/spec/02-execution-environment/04-runners.rst index 9343e6068..6bcfb4134 100644 --- a/doc/website/src/spec/02-execution-environment/04-runners.rst +++ b/doc/website/src/spec/02-execution-environment/04-runners.rst @@ -18,7 +18,9 @@ forms (see the ``runner-id`` definition in the runner.json schema): provided for convenience; ``hash`` is a hash of its contents (see `Hash Format`_). - ``contract`` — the runner of the contract currently being executed. - ``chain:
::`` — a runner code blob read from a storage slot - of an arbitrary contract (``a`` = accepted, ``f`` = finalized). + of an arbitrary contract (``a`` = accepted, ``f`` = finalized). ``
`` is + a ``0x`` 20 byte hex address and ```` is a :term:`SlotID` encoded with + :doc:`../../04-contract-interface/06-gvm32`. - ``custom:`` — a runner registered at runtime via the ``RegisterRunner`` ``gl_call``, looked up by its hash. @@ -28,27 +30,10 @@ as human-readable ids. Hash Format ~~~~~~~~~~~ -Hash is SHA3 256-bit hash, converted to a string with following algorithm: - -.. code-block:: python - - def digest_to_hash_id(got_hash: bytes) -> str: - chars = '0123456789abcdfghijklmnpqrsvwxyz' - - bytes_count = len(got_hash) - base32_len = (bytes_count * 8 - 1) // 5 + 1 - - my_hash_arr = [] - for n in range(base32_len - 1, -1, -1): - b = n * 5 - i = b // 8 - j = b % 8 - c = (got_hash[i] >> j) | (0 if i >= bytes_count - 1 else got_hash[i + 1] << (8 - j)) - my_hash_arr.append(chars[c & 0x1F]) - - return ''.join(my_hash_arr) - -This ensures that it contains no fs-illegal characters and is case insensitive. +``hash`` is the SHA3 256-bit hash of the runner's contents, encoded with +:doc:`../../04-contract-interface/06-gvm32` (GVM32, a lowercase Crockford +Base32). This keeps it free of filesystem-illegal characters and +case-insensitive. Runner Layout ------------- diff --git a/executor/src/host/message.rs b/executor/src/host/message.rs index 9d6b046c4..c718f8213 100644 --- a/executor/src/host/message.rs +++ b/executor/src/host/message.rs @@ -94,3 +94,9 @@ impl From<&[u8; 32]> for SlotID { SlotID(*value) } } + +impl std::fmt::Display for SlotID { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(&genlayer_sdk::gvm32::encode(&self.0)) + } +} diff --git a/executor/src/runners/mod.rs b/executor/src/runners/mod.rs index f028caaca..a7c911ddc 100644 --- a/executor/src/runners/mod.rs +++ b/executor/src/runners/mod.rs @@ -31,7 +31,7 @@ pub fn append_runner_subpath(id: &str, hash: &str, path: &mut std::path::PathBuf /// - `chain:
::` — read the runner code blob from a storage /// slot of an arbitrary contract. `address` is a `0x`-prefixed 20 byte hex /// address, `a`/`f` selects accepted (latest non final) / finalized state and -/// `slot` is a `0x`-prefixed 32 byte hex slot id. +/// `slot` is a 32 byte slot id encoded with GVM32 (Crockford Base32). /// - `custom:` — a runner registered at runtime, looked up by its hash. pub enum IdUnresolved { Builtin { @@ -108,10 +108,10 @@ impl Id { _ => 'a', }; symbol_table::GlobalSymbol::from(format!( - "chain:0x{}:{}:0x{}", + "chain:0x{}:{}:{}", hex::encode(address.raw()), on, - hex::encode(slot.raw()) + genlayer_sdk::gvm32::encode(&slot.raw()) )) } Id::Custom { hash } => custom_runner_id(*hash), @@ -153,7 +153,8 @@ pub fn parse_runner_id(id: &str) -> Option { "f" => crate::public_abi::StorageType::LatestFinal, _ => return None, }; - let slot = crate::SlotID::from_bytes(parse_hex_fixed::<32>(slot)?); + let slot: [u8; 32] = genlayer_sdk::gvm32::decode(slot)?.try_into().ok()?; + let slot = crate::SlotID::from_bytes(slot); return Some(IdUnresolved::Chain { address, on, slot }); } @@ -191,7 +192,7 @@ pub fn custom_runner_hash(code: &[u8]) -> symbol_table::GlobalSymbol { use sha3::Digest as _; let mut digest = sha3::Sha3_256::new(); digest.update(code); - symbol_table::GlobalSymbol::from(hex::encode(digest.finalize())) + symbol_table::GlobalSymbol::from(genlayer_sdk::gvm32::encode(digest.finalize().as_slice())) } /// Builds the canonical `custom:` runner id from its hash. @@ -303,7 +304,7 @@ mod tests { format!("0x{}1", "0".repeat(39)) } fn slot64() -> String { - format!("0x{}2", "0".repeat(63)) + genlayer_sdk::gvm32::encode(&[0x11u8; 32]) } #[test] diff --git a/runners/support/default.nix b/runners/support/default.nix index fc484b17e..0f0c552bf 100644 --- a/runners/support/default.nix +++ b/runners/support/default.nix @@ -15,7 +15,8 @@ in rec { add-mod-name = import ./tools/genvm-wasm-add-mod-name args; }; - hashToIDHash = hash: if hash == "test" then "test" else builtins.convertHash { inherit hash; toHashFormat = "nix32"; }; + gvm32 = import ./gvm32.nix { lib = pkgs.lib; }; + hashToIDHash = hash: if hash == "test" then "test" else gvm32.encodeHex (builtins.convertHash { inherit hash; toHashFormat = "base16"; }); package = { id, hash, baseDerivation }: { inherit id hash; diff --git a/support/runner-script.py b/support/runner-script.py index 23c379ccc..c1a812191 100755 --- a/support/runner-script.py +++ b/support/runner-script.py @@ -12,7 +12,7 @@ import hashlib -HASH_VALID_CHARS = '0123456789abcdfghijklmnpqrsvwxyz' +HASH_VALID_CHARS = '0123456789abcdefghjkmnpqrstvwxyz' ORIGINAL_ENV = os.environ.copy() if 'ORIGINAL_PATH' in ORIGINAL_ENV: @@ -22,20 +22,20 @@ def digest_to_hash_id(got_hash: bytes) -> str: - chars = '0123456789abcdfghijklmnpqrsvwxyz' - - bytes_count = len(got_hash) - base32_len = (bytes_count * 8 - 1) // 5 + 1 - - my_hash_arr = [] - for n in range(base32_len - 1, -1, -1): - b = n * 5 - i = b // 8 - j = b % 8 - c = (got_hash[i] >> j) | (0 if i >= bytes_count - 1 else got_hash[i + 1] << (8 - j)) - my_hash_arr.append(chars[c & 0x1F]) - - return ''.join(my_hash_arr) + # Crockford's Base32 (see runners/genlayer-py-std/src/genlayer/gvm32.py and + # executor/crates/sdk-rs/src/gvm32.rs): big-endian, no padding. + out = [] + value = 0 + bits = 0 + for byte in got_hash: + value = (value << 8) | byte + bits += 8 + while bits >= 5: + bits -= 5 + out.append(HASH_VALID_CHARS[(value >> bits) & 0x1F]) + if bits > 0: + out.append(HASH_VALID_CHARS[(value << (5 - bits)) & 0x1F]) + return ''.join(out) def check_bytes(data: bytes, hash: str) -> bool: diff --git a/tests/cases/stable/runners/register-runner.0.stdout b/tests/cases/stable/runners/register-runner.0.stdout index 4bc51f8c2..b0c147d23 100644 --- a/tests/cases/stable/runners/register-runner.0.stdout +++ b/tests/cases/stable/runners/register-runner.0.stdout @@ -1,2 +1,2 @@ -custom:f5431a053008f57effd6036d17f8c39439ae6511f407dcdd62dbcf27ee4d4b4c +custom:yn1hm19g13tqxzyp0dphfy63jgwtws8hyg3xsqb2vf7jfvjd9d60 executed with `Return(null)` diff --git a/tests/cases/stable/runners/register_loop.0.stdout b/tests/cases/stable/runners/register_loop.0.stdout index 91d09e7d5..76bab1f7a 100644 --- a/tests/cases/stable/runners/register_loop.0.stdout +++ b/tests/cases/stable/runners/register_loop.0.stdout @@ -1,2 +1,2 @@ -custom:12cf083cef24fc898fdae3fada0792f6efe309557ac1ea02ec15ea58f136afa4 +custom:2b7ggf7f4ky8k3ytwfxdm1wjyvqy62anfb0ym0qc2qn5hw9pnyj0 executed with `Return(null)` From e30b0272530ab15e5753aa606a26fb88b4e34cbc Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Mon, 22 Jun 2026 22:40:28 +0900 Subject: [PATCH 035/124] =?UTF-8?q?feat(calldata):=20add=20Address::checks?= =?UTF-8?q?um=5Fhex=20(EIP-55)=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/crates/calldata/Cargo.lock | 80 +++++++++++++++++++++++++++ executor/crates/calldata/Cargo.toml | 2 + executor/crates/calldata/src/types.rs | 23 ++++++++ 3 files changed, 105 insertions(+) diff --git a/executor/crates/calldata/Cargo.lock b/executor/crates/calldata/Cargo.lock index 434876756..5d204f1f7 100644 --- a/executor/crates/calldata/Cargo.lock +++ b/executor/crates/calldata/Cargo.lock @@ -53,6 +53,15 @@ dependencies = [ "wyz", ] +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "bumpalo" version = "3.20.2" @@ -136,12 +145,41 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + [[package]] name = "crunchy" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -172,6 +210,16 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "genlayer_calldata" version = "0.0.2" @@ -185,6 +233,7 @@ dependencies = [ "num-bigint", "primitive-types", "serde", + "sha3", ] [[package]] @@ -301,6 +350,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "keccak" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" +dependencies = [ + "cpufeatures", +] + [[package]] name = "libc" version = "0.2.183" @@ -523,6 +581,16 @@ dependencies = [ "syn", ] +[[package]] +name = "sha3" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77fd7028345d415a4034cf8777cd4f8ab1851274233b45f84e3d955502d93874" +dependencies = [ + "digest", + "keccak", +] + [[package]] name = "shlex" version = "1.3.0" @@ -582,6 +650,12 @@ dependencies = [ "winnow", ] +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + [[package]] name = "uint" version = "0.10.0" @@ -606,6 +680,12 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" diff --git a/executor/crates/calldata/Cargo.toml b/executor/crates/calldata/Cargo.toml index 6d439c06a..78b591c35 100644 --- a/executor/crates/calldata/Cargo.toml +++ b/executor/crates/calldata/Cargo.toml @@ -30,6 +30,7 @@ arbitrary = ["dep:arbitrary"] genlayer_calldata_derive = { path = "../calldata-derive" } hex = "0.4.3" num-bigint = {version = "0.4.6", features = ["serde"] } +sha3 = { version = "0.10" } serde = { version = "1.0", features = ["derive"] } arbitrary = { version = "1.0", optional = true } primitive-types = { version = "0.13", features = ["impl-serde"] } @@ -38,3 +39,4 @@ chrono = { version = "0.4", features = ["serde"] } [dev-dependencies] afl = { version = "0.15.18", features = ["no_cfg_fuzzing"] } +hex = "0.4.3" diff --git a/executor/crates/calldata/src/types.rs b/executor/crates/calldata/src/types.rs index 3329f449b..917e11890 100644 --- a/executor/crates/calldata/src/types.rs +++ b/executor/crates/calldata/src/types.rs @@ -37,6 +37,29 @@ impl Address { self.0 } + /// Returns the address as an [EIP-55](https://eips.ethereum.org/EIPS/eip-55) + /// mixed-case checksummed hex string (40 chars, no `0x` prefix). + pub fn checksum_hex(self) -> String { + use sha3::Digest as _; + + let lower = hex::encode(self.0); + let hash = sha3::Keccak256::digest(lower.as_bytes()); + + lower + .char_indices() + .map(|(i, c)| { + // digits stay as-is; letters are upper-cased when the matching + // hex nibble of the hash is >= 8 + let nibble = hash[i / 2] >> (if i % 2 == 0 { 4 } else { 0 }) & 0x0f; + if c.is_ascii_alphabetic() && nibble >= 8 { + c.to_ascii_uppercase() + } else { + c + } + }) + .collect() + } + pub fn ref_mut(&mut self) -> &mut [u8; ADDRESS_SIZE] { &mut self.0 } From 0e9f52828aec0643caaf93f28a9103d44c3e1888 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Mon, 22 Jun 2026 22:40:29 +0900 Subject: [PATCH 036/124] =?UTF-8?q?docs(claude):=20rust-test-style=20?= =?UTF-8?q?=E2=80=94=20public-API=20tests=20belong=20in=20tests/=20?= =?UTF-8?q?=F0=9F=93=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/skills/rust-test-style/SKILL.md | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/.claude/skills/rust-test-style/SKILL.md b/.claude/skills/rust-test-style/SKILL.md index 379c2b0d5..364d02484 100644 --- a/.claude/skills/rust-test-style/SKILL.md +++ b/.claude/skills/rust-test-style/SKILL.md @@ -15,16 +15,29 @@ To run these tests, see the `/test` skill (`--filter-tag rust`). ## Where tests go +**Decision rule — default to a separate file.** If the item under test is +reachable from the crate's public API (a `pub fn`/`pub` type, even via a +re-export), its test goes in its own `tests/.rs` file. Use an inline +`#[cfg(test)] mod tests` **only** when the test must reach a *private* item that +cannot be exercised through the public API. A public function tested inline is a +review finding — move it to `tests/`. + Two locations, both in use: 1. **Integration tests** — one file per concern under the crate's `tests/` dir. - Preferred for exercising a crate's public API. Each `tests/*.rs` file is its - own compilation unit and gets its own runner case. + **This is the default** for anything testable through the public API. Each + `tests/*.rs` file is its own compilation unit (a separate crate) and gets its + own runner case. - e.g. `executor/crates/calldata/tests/derive_decode.rs`, + `executor/crates/calldata/tests/address_checksum.rs`, `executor/crates/common/tests/expr.rs`, `modules/implementation/tests/test_rat.rs` + - Because each is a separate crate, it sees only the library crate plus + `[dev-dependencies]` — **not** the library's regular `[dependencies]`. If a + test needs a util the crate already depends on (e.g. `hex`), add it to + `[dev-dependencies]` too. 2. **Inline unit tests** — `#[cfg(test)] mod tests { ... }` at the bottom of a - `src/*.rs` file, for testing private items. e.g. + `src/*.rs` file, reserved for testing **private** items. e.g. `executor/crates/calldata/src/lib.rs`, `executor/crates/common/src/logger/mod.rs`. ```rust From 4659283f7353d1f0ea745160895896b43cfe6a25 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Mon, 22 Jun 2026 22:49:34 +0900 Subject: [PATCH 037/124] =?UTF-8?q?feat(calldata):=20checksum=5Fhex=20retu?= =?UTF-8?q?rns=20[u8;40];=20canonical=20runner=20id=20uses=20EIP-55=20chec?= =?UTF-8?q?ksum=20address=20=E2=99=BB=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/Cargo.lock | 1 + executor/crates/calldata/src/types.rs | 43 +++++++++++-------- .../crates/calldata/tests/address_checksum.rs | 23 ++++++++++ executor/src/runners/mod.rs | 3 +- executor/tests/runner_id.rs | 28 ++++++++++++ modules/implementation/Cargo.lock | 1 + 6 files changed, 81 insertions(+), 18 deletions(-) create mode 100644 executor/crates/calldata/tests/address_checksum.rs create mode 100644 executor/tests/runner_id.rs diff --git a/executor/Cargo.lock b/executor/Cargo.lock index 51b3d7b4b..0a531bd0b 100644 --- a/executor/Cargo.lock +++ b/executor/Cargo.lock @@ -958,6 +958,7 @@ dependencies = [ "num-bigint", "primitive-types", "serde", + "sha3", ] [[package]] diff --git a/executor/crates/calldata/src/types.rs b/executor/crates/calldata/src/types.rs index 917e11890..7e1bb1e56 100644 --- a/executor/crates/calldata/src/types.rs +++ b/executor/crates/calldata/src/types.rs @@ -7,13 +7,19 @@ pub struct Address(pub(super) [u8; ADDRESS_SIZE]); impl std::fmt::Debug for Address { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_fmt(format_args!("addr#{}", hex::encode(self.0))) + f.write_fmt(format_args!( + "addr#{}", + std::str::from_utf8(&self.checksum_hex()).map_err(|_| std::fmt::Error)? + )) } } impl std::fmt::Display for Address { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "addr#{}", hex::encode(self.0)) + f.write_fmt(format_args!( + "addr#{}", + std::str::from_utf8(&self.checksum_hex()).map_err(|_| std::fmt::Error)? + )) } } @@ -38,26 +44,29 @@ impl Address { } /// Returns the address as an [EIP-55](https://eips.ethereum.org/EIPS/eip-55) - /// mixed-case checksummed hex string (40 chars, no `0x` prefix). - pub fn checksum_hex(self) -> String { + /// mixed-case checksummed hex, as 40 ASCII bytes (no `0x` prefix). + pub fn checksum_hex(self) -> [u8; 40] { use sha3::Digest as _; - let lower = hex::encode(self.0); - let hash = sha3::Keccak256::digest(lower.as_bytes()); + const HEX: &[u8; 16] = b"0123456789abcdef"; + let mut out = [0u8; 40]; + for (i, &b) in self.0.iter().enumerate() { + out[i * 2] = HEX[(b >> 4) as usize]; + out[i * 2 + 1] = HEX[(b & 0x0f) as usize]; + } - lower - .char_indices() - .map(|(i, c)| { - // digits stay as-is; letters are upper-cased when the matching - // hex nibble of the hash is >= 8 + // hash of the lowercase hex; a hex letter is upper-cased when the + // matching hash nibble is >= 8 + let hash = sha3::Keccak256::digest(out); + for i in 0..out.len() { + if out[i].is_ascii_alphabetic() { let nibble = hash[i / 2] >> (if i % 2 == 0 { 4 } else { 0 }) & 0x0f; - if c.is_ascii_alphabetic() && nibble >= 8 { - c.to_ascii_uppercase() - } else { - c + if nibble >= 8 { + out[i] = out[i].to_ascii_uppercase(); } - }) - .collect() + } + } + out } pub fn ref_mut(&mut self) -> &mut [u8; ADDRESS_SIZE] { diff --git a/executor/crates/calldata/tests/address_checksum.rs b/executor/crates/calldata/tests/address_checksum.rs new file mode 100644 index 000000000..2581abdd6 --- /dev/null +++ b/executor/crates/calldata/tests/address_checksum.rs @@ -0,0 +1,23 @@ +use genlayer_calldata::Address; + +fn addr(lower_hex: &str) -> Address { + let mut b = [0u8; 20]; + hex::decode_to_slice(lower_hex, &mut b).unwrap(); + Address::from(b) +} + +#[test] +fn eip55_checksum() { + // vectors from EIP-55 (https://eips.ethereum.org/EIPS/eip-55) + for expected in [ + "5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed", + "fB6916095ca1df60bB79Ce92cE3Ea74c37c5d359", + "dbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB", + "D1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb", + ] { + assert_eq!( + addr(&expected.to_lowercase()).checksum_hex().as_slice(), + expected.as_bytes() + ); + } +} diff --git a/executor/src/runners/mod.rs b/executor/src/runners/mod.rs index a7c911ddc..0b853eea0 100644 --- a/executor/src/runners/mod.rs +++ b/executor/src/runners/mod.rs @@ -107,9 +107,10 @@ impl Id { crate::public_abi::StorageType::LatestFinal => 'f', _ => 'a', }; + let address = address.checksum_hex(); symbol_table::GlobalSymbol::from(format!( "chain:0x{}:{}:{}", - hex::encode(address.raw()), + std::str::from_utf8(&address).expect("checksum hex is ascii"), on, genlayer_sdk::gvm32::encode(&slot.raw()) )) diff --git a/executor/tests/runner_id.rs b/executor/tests/runner_id.rs new file mode 100644 index 000000000..2c5fcf715 --- /dev/null +++ b/executor/tests/runner_id.rs @@ -0,0 +1,28 @@ +use genvm::calldata::Address; +use genvm::public_abi::StorageType; +use genvm::runners::Id; +use genvm::SlotID; + +#[test] +fn chain_canonical_uses_checksum_address() { + // EIP-55 address whose checksum form has mixed case + let address = Address::from([ + 0x5a, 0xae, 0xb6, 0x05, 0x3f, 0x3e, 0x94, 0xc9, 0xb9, 0xa0, 0x9f, 0x33, 0x66, 0x94, 0x35, + 0xe7, 0xef, 0x1b, 0xea, 0xed, + ]); + + let id = Id::Chain { + address, + on: StorageType::LatestNonFinal, + slot: SlotID::ZERO, + }; + + let expected = format!( + "chain:0x{}:a:{}", + std::str::from_utf8(&address.checksum_hex()).unwrap(), + "0".repeat(52), // gvm32 of 32 zero bytes + ); + assert_eq!(id.canonical().as_str(), expected.as_str()); + // sanity: the address part is genuinely mixed-case (checksummed), not lowercase + assert!(expected.contains("5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed")); +} diff --git a/modules/implementation/Cargo.lock b/modules/implementation/Cargo.lock index 4efd92d77..cd8d58dc0 100644 --- a/modules/implementation/Cargo.lock +++ b/modules/implementation/Cargo.lock @@ -979,6 +979,7 @@ dependencies = [ "num-bigint", "primitive-types", "serde", + "sha3", ] [[package]] From 33157e28729e3c2c520f7adfa7f2af70e2840638 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Mon, 22 Jun 2026 22:52:02 +0900 Subject: [PATCH 038/124] =?UTF-8?q?refactor(calldata):=20add=20checksum=5F?= =?UTF-8?q?hex=5Fstring=20(String)=20alongside=20checksum=5Fhex=20([u8;40]?= =?UTF-8?q?)=20=E2=99=BB=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/crates/calldata/src/types.rs | 15 +++++++-------- .../crates/calldata/tests/address_checksum.rs | 7 +++---- executor/src/runners/mod.rs | 3 +-- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/executor/crates/calldata/src/types.rs b/executor/crates/calldata/src/types.rs index 7e1bb1e56..f94215d50 100644 --- a/executor/crates/calldata/src/types.rs +++ b/executor/crates/calldata/src/types.rs @@ -7,19 +7,13 @@ pub struct Address(pub(super) [u8; ADDRESS_SIZE]); impl std::fmt::Debug for Address { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_fmt(format_args!( - "addr#{}", - std::str::from_utf8(&self.checksum_hex()).map_err(|_| std::fmt::Error)? - )) + f.write_fmt(format_args!("addr#{}", self.checksum_hex_string())) } } impl std::fmt::Display for Address { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_fmt(format_args!( - "addr#{}", - std::str::from_utf8(&self.checksum_hex()).map_err(|_| std::fmt::Error)? - )) + f.write_fmt(format_args!("addr#{}", self.checksum_hex_string())) } } @@ -69,6 +63,11 @@ impl Address { out } + /// Like [`Address::checksum_hex`], but as an owned `String`. + pub fn checksum_hex_string(self) -> String { + self.checksum_hex().iter().map(|&b| b as char).collect() + } + pub fn ref_mut(&mut self) -> &mut [u8; ADDRESS_SIZE] { &mut self.0 } diff --git a/executor/crates/calldata/tests/address_checksum.rs b/executor/crates/calldata/tests/address_checksum.rs index 2581abdd6..287932b87 100644 --- a/executor/crates/calldata/tests/address_checksum.rs +++ b/executor/crates/calldata/tests/address_checksum.rs @@ -15,9 +15,8 @@ fn eip55_checksum() { "dbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB", "D1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb", ] { - assert_eq!( - addr(&expected.to_lowercase()).checksum_hex().as_slice(), - expected.as_bytes() - ); + let a = addr(&expected.to_lowercase()); + assert_eq!(a.checksum_hex().as_slice(), expected.as_bytes()); + assert_eq!(a.checksum_hex_string(), expected); } } diff --git a/executor/src/runners/mod.rs b/executor/src/runners/mod.rs index 0b853eea0..9327b2e4f 100644 --- a/executor/src/runners/mod.rs +++ b/executor/src/runners/mod.rs @@ -107,10 +107,9 @@ impl Id { crate::public_abi::StorageType::LatestFinal => 'f', _ => 'a', }; - let address = address.checksum_hex(); symbol_table::GlobalSymbol::from(format!( "chain:0x{}:{}:{}", - std::str::from_utf8(&address).expect("checksum hex is ascii"), + address.checksum_hex_string(), on, genlayer_sdk::gvm32::encode(&slot.raw()) )) From 4ebc3d857996381aa8b05ef1aa4e00d024a29261 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Mon, 22 Jun 2026 23:14:14 +0900 Subject: [PATCH 039/124] =?UTF-8?q?feat(common):=20add=20Bytes32Hash=20typ?= =?UTF-8?q?e=20with=20gvm32=20formatting=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/crates/common/Cargo.lock | 1 + executor/crates/common/src/bytes32.rs | 53 +++++++++++++++++++++++++ executor/crates/common/src/lib.rs | 3 ++ executor/crates/common/tests/bytes32.rs | 19 +++++++++ 4 files changed, 76 insertions(+) create mode 100644 executor/crates/common/src/bytes32.rs create mode 100644 executor/crates/common/tests/bytes32.rs diff --git a/executor/crates/common/Cargo.lock b/executor/crates/common/Cargo.lock index 539ec981c..68c55320b 100644 --- a/executor/crates/common/Cargo.lock +++ b/executor/crates/common/Cargo.lock @@ -485,6 +485,7 @@ dependencies = [ "num-bigint", "primitive-types", "serde", + "sha3", ] [[package]] diff --git a/executor/crates/common/src/bytes32.rs b/executor/crates/common/src/bytes32.rs new file mode 100644 index 000000000..964a5000d --- /dev/null +++ b/executor/crates/common/src/bytes32.rs @@ -0,0 +1,53 @@ +//! A 32-byte hash (runner content hash, `custom:` hash, …) with GVM32 formatting. + +/// A 32-byte hash value. Formats (and parses) as GVM32 / Crockford Base32 (see +/// [`genlayer_sdk::gvm32`]). +#[derive( + Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, serde::Serialize, serde::Deserialize, +)] +pub struct Bytes32Hash(pub [u8; 32]); + +impl Bytes32Hash { + pub const ZERO: Self = Self([0; 32]); + + pub const fn from_bytes(bytes: [u8; 32]) -> Self { + Self(bytes) + } + + pub fn as_bytes(&self) -> &[u8; 32] { + &self.0 + } + + pub fn raw(&self) -> [u8; 32] { + self.0 + } + + /// The GVM32 (Crockford Base32) textual form. + pub fn to_gvm32(&self) -> String { + genlayer_sdk::gvm32::encode(&self.0) + } + + /// Parses a hash from its GVM32 form. Returns `None` for an invalid encoding + /// or one that does not decode to exactly 32 bytes. + pub fn from_gvm32(s: &str) -> Option { + genlayer_sdk::gvm32::decode(s)?.try_into().ok().map(Self) + } +} + +impl From<[u8; 32]> for Bytes32Hash { + fn from(bytes: [u8; 32]) -> Self { + Self(bytes) + } +} + +impl std::fmt::Display for Bytes32Hash { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(&self.to_gvm32()) + } +} + +impl std::fmt::Debug for Bytes32Hash { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_fmt(format_args!("hash#{}", self.to_gvm32())) + } +} diff --git a/executor/crates/common/src/lib.rs b/executor/crates/common/src/lib.rs index c4e6132cc..a29f5b5a7 100644 --- a/executor/crates/common/src/lib.rs +++ b/executor/crates/common/src/lib.rs @@ -5,6 +5,9 @@ use serde::{Deserialize, Serialize}; pub use genlayer_sdk::calldata; +pub mod bytes32; +pub use bytes32::Bytes32Hash; + pub mod cancellation; pub mod io; pub mod logger; diff --git a/executor/crates/common/tests/bytes32.rs b/executor/crates/common/tests/bytes32.rs new file mode 100644 index 000000000..8f0d090cf --- /dev/null +++ b/executor/crates/common/tests/bytes32.rs @@ -0,0 +1,19 @@ +use genvm_common::Bytes32Hash; + +#[test] +fn gvm32_round_trip() { + let bytes = [0xabu8; 32]; + let h = Bytes32Hash::from_bytes(bytes); + + let s = h.to_gvm32(); + assert_eq!(s.len(), 52); // ceil(256 / 5) + assert_eq!(Bytes32Hash::from_gvm32(&s), Some(h)); + assert_eq!(h.to_string(), s); // Display == gvm32 + assert_eq!(h.as_bytes(), &bytes); +} + +#[test] +fn from_gvm32_rejects_invalid() { + assert_eq!(Bytes32Hash::from_gvm32("abc"), None); // decodes to < 32 bytes + assert_eq!(Bytes32Hash::from_gvm32(""), None); // 0 bytes +} From e510fe885f1ef911568783f1cdf4a978f590d7f4 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Mon, 22 Jun 2026 23:14:15 +0900 Subject: [PATCH 040/124] =?UTF-8?q?refactor(executor):=20use=20Bytes32Hash?= =?UTF-8?q?=20for=20custom=20runner=20hashes=20=E2=99=BB=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/src/rt/supervisor/actions.rs | 39 ++++++++++++-------- executor/src/rt/supervisor/mod.rs | 8 ++-- executor/src/runners/mod.rs | 32 ++++++++-------- tests/cases/stable/runners/custom_missing.py | 2 +- 4 files changed, 44 insertions(+), 37 deletions(-) diff --git a/executor/src/rt/supervisor/actions.rs b/executor/src/rt/supervisor/actions.rs index 66eee99f0..2c6fc7468 100644 --- a/executor/src/rt/supervisor/actions.rs +++ b/executor/src/rt/supervisor/actions.rs @@ -46,7 +46,7 @@ enum ResolvedKind { slot: crate::SlotID, }, /// `custom:` — a runner registered at runtime. - Custom { hash: symbol_table::GlobalSymbol }, + Custom { hash: Bytes32Hash }, } /// A runner id resolved to its canonical cache key together with the way it @@ -73,8 +73,9 @@ fn resolve_runner( )); }; - match parsed.resolve(contract_address, state, code_slot) { - runners::Id::Builtin { name, hash } => { + let resolved: runners::Id = match parsed.resolve(contract_address, state, code_slot) { + runners::IdUnresolved::Contract => unreachable!("contract is resolved to chain"), + runners::IdUnresolved::Builtin { name, hash } => { let hash = if hash.as_str() == "test" || hash.as_str() == "latest" { if !supervisor.shared_data.debug_mode { log_warn!(":test/ :latest runner used in non-debug mode, this is not allowed"); @@ -98,20 +99,26 @@ fn resolve_runner( anyhow::bail!("runner {}:{} not found", name, hash); } - Ok(Resolved { - id: runners::Id::Builtin { name, hash }.canonical(), - kind: ResolvedKind::Disk { name, hash }, - }) + runners::Id::Builtin { name, hash } } - runners::Id::Chain { address, on, slot } => Ok(Resolved { - id: runners::Id::Chain { address, on, slot }.canonical(), - kind: ResolvedKind::Chain { address, on, slot }, - }), - runners::Id::Custom { hash } => Ok(Resolved { - id: runners::Id::Custom { hash }.canonical(), - kind: ResolvedKind::Custom { hash }, - }), - } + runners::IdUnresolved::Chain { address, on, slot } => { + runners::Id::Chain { address, on, slot } + } + runners::IdUnresolved::Custom { hash } => { + let hash = Bytes32Hash::from_gvm32(hash.as_str()).ok_or_else(|| { + make_malformed_runner_error("custom runner hash is not valid gvm32") + })?; + runners::Id::Custom { hash } + } + }; + + let id = resolved.canonical(); + let kind = match resolved { + runners::Id::Builtin { name, hash } => ResolvedKind::Disk { name, hash }, + runners::Id::Chain { address, on, slot } => ResolvedKind::Chain { address, on, slot }, + runners::Id::Custom { hash } => ResolvedKind::Custom { hash }, + }; + Ok(Resolved { id, kind }) } /// Loads (and caches) the archive for an already-resolved runner. diff --git a/executor/src/rt/supervisor/mod.rs b/executor/src/rt/supervisor/mod.rs index 942b9f4ce..97e9fd479 100644 --- a/executor/src/rt/supervisor/mod.rs +++ b/executor/src/rt/supervisor/mod.rs @@ -78,7 +78,7 @@ pub struct Supervisor { /// Runners registered at runtime via `gl_call`, looked up by the /// `custom:` runner id. Empty until a contract registers one. - custom_runners: dashmap::DashMap, + custom_runners: dashmap::DashMap, pub(crate) engines: rt::DetNondet, pub(crate) host: Arc, @@ -225,7 +225,7 @@ impl Supervisor { rt::vm::storage::Limiter::new(self.shared_data.gep(|x| &x.data_fees_limit)) } - pub fn get_custom_runner(&self, hash: GlobalSymbol) -> Option { + pub fn get_custom_runner(&self, hash: Bytes32Hash) -> Option { self.custom_runners.get(&hash).map(|r| r.clone()) } @@ -648,7 +648,7 @@ async fn nondet_vm_processor( /// Core of [`Supervisor::register_custom_runner`]; charges the parsed archive /// against `limiter` only on the first registration of a given hash. fn register_custom_runner_into( - custom_runners: &dashmap::DashMap, + custom_runners: &dashmap::DashMap, code: bytes::Bytes, limiter: &rt::memlimiter::Limiter, ) -> anyhow::Result { @@ -664,7 +664,7 @@ fn register_custom_runner_into( slot.insert(archive); } - Ok(runners::custom_runner_id(hash)) + Ok(runners::Id::Custom { hash }.canonical()) } #[cfg(test)] diff --git a/executor/src/runners/mod.rs b/executor/src/runners/mod.rs index 9327b2e4f..90433f78e 100644 --- a/executor/src/runners/mod.rs +++ b/executor/src/runners/mod.rs @@ -60,7 +60,7 @@ pub enum Id { slot: crate::SlotID, }, Custom { - hash: symbol_table::GlobalSymbol, + hash: Bytes32Hash, }, } @@ -76,16 +76,14 @@ impl IdUnresolved { contract_address: calldata::Address, state: crate::public_abi::StorageType, code_slot: crate::SlotID, - ) -> Id { + ) -> IdUnresolved { match self { - IdUnresolved::Contract => Id::Chain { + IdUnresolved::Contract => IdUnresolved::Chain { address: contract_address, on: state, slot: code_slot, }, - IdUnresolved::Builtin { name, hash } => Id::Builtin { name, hash }, - IdUnresolved::Chain { address, on, slot } => Id::Chain { address, on, slot }, - IdUnresolved::Custom { hash } => Id::Custom { hash }, + other => other, } } } @@ -114,7 +112,11 @@ impl Id { genlayer_sdk::gvm32::encode(&slot.raw()) )) } - Id::Custom { hash } => custom_runner_id(*hash), + Id::Custom { hash } => { + let mut id = String::from("custom:"); + id.push_str(&hash.to_gvm32()); + symbol_table::GlobalSymbol::from(id) + } } } } @@ -188,18 +190,16 @@ pub fn parse_runner_id(id: &str) -> Option { } /// Derives the hash component of a `custom:` runner id from its code. -pub fn custom_runner_hash(code: &[u8]) -> symbol_table::GlobalSymbol { +pub fn custom_runner_hash(code: &[u8]) -> Bytes32Hash { use sha3::Digest as _; let mut digest = sha3::Sha3_256::new(); digest.update(code); - symbol_table::GlobalSymbol::from(genlayer_sdk::gvm32::encode(digest.finalize().as_slice())) -} - -/// Builds the canonical `custom:` runner id from its hash. -pub fn custom_runner_id(hash: symbol_table::GlobalSymbol) -> symbol_table::GlobalSymbol { - let mut id = String::from("custom:"); - id.push_str(hash.as_str()); - symbol_table::GlobalSymbol::from(id) + let arr: [u8; 32] = digest + .finalize() + .as_slice() + .try_into() + .expect("sha3-256 is 32 bytes"); + Bytes32Hash::from_bytes(arr) } pub struct ArchiveCache { diff --git a/tests/cases/stable/runners/custom_missing.py b/tests/cases/stable/runners/custom_missing.py index 81091e26a..51708489b 100644 --- a/tests/cases/stable/runners/custom_missing.py +++ b/tests/cases/stable/runners/custom_missing.py @@ -1,2 +1,2 @@ -# { "Depends": "custom:0123abcd" } +# { "Depends": "custom:0000000000000000000000000000000000000000000000000000" } exit(0) From 19718991fe73918af7cc7a45d470599f4e4347cc Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Mon, 22 Jun 2026 23:59:53 +0900 Subject: [PATCH 041/124] =?UTF-8?q?refactor(runners):=20builtin/custom=20r?= =?UTF-8?q?unner=20hash=20is=20Bytes32Hash;=20dev=20"test"=20hash=20is=20g?= =?UTF-8?q?vm32=20test0000=E2=80=A6=20=F0=9F=94=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Builtin/Custom Id hash fields become Bytes32Hash (gvm32). The dev-mode magic hash resolves to the gvm32 string "test" padded with 0s to 52 chars (decodes to d3b3a0…00), consistent across the rust executor, the on-disk runner layout, and all.json/latest.json. The latest/all.json generators and the debug/universal layout views now derive the hash from each runner uid (gvm32) instead of recomputing via convertHash nix32 / raw "test". --- configure.rb | 4 ++-- executor/src/rt/supervisor/actions.rs | 27 +++++++++++++++++-------- executor/src/runners/mod.rs | 24 ++++++++++++++-------- runners/support/default.nix | 4 +++- runners/support/views/all-universal.nix | 2 +- runners/support/views/debug-build.nix | 6 ++---- 6 files changed, 43 insertions(+), 24 deletions(-) diff --git a/configure.rb b/configure.rb index d2151e5a3..d1ad1afe5 100755 --- a/configure.rb +++ b/configure.rb @@ -486,13 +486,13 @@ def generator.register_cargo(rel_path, extra_args: [], build_to: nil) runners_nix_inputs = $source_dir.join('runners').glob('**/*.nix') generator.build(:nix_eval, 'out/executor/vTEST/data/latest.json') do - var 'expr', 'let drv = import ./runners { host-system = builtins.currentSystem; } ; conv-hash = hash: if hash == "test" then "test" else builtins.convertHash { inherit hash; toHashFormat = "nix32"; } ; in builtins.listToAttrs (builtins.map (x: { name = x.id; value = conv-hash x.hash; }) drv)' + var 'expr', 'let drv = import ./runners { host-system = builtins.currentSystem; } ; hash-of = x: builtins.head (builtins.tail (builtins.match "([^:]+):(.*)" x.uid)) ; in builtins.listToAttrs (builtins.map (x: { name = x.id; value = hash-of x; }) drv)' var 'wd', $source_dir add_implicit_dependency runners_nix_inputs end generator.build(:nix_eval, 'out/executor/vTEST/data/all.json') do - var 'expr', 'let drv = import ./runners { host-system = builtins.currentSystem; } ; conv-hash = hash: if hash == "test" then "test" else builtins.convertHash { inherit hash; toHashFormat = "nix32"; } ; in builtins.listToAttrs (builtins.map (x: { name = x.id; value = [ (conv-hash x.hash) ]; }) drv)' + var 'expr', 'let drv = import ./runners { host-system = builtins.currentSystem; } ; hash-of = x: builtins.head (builtins.tail (builtins.match "([^:]+):(.*)" x.uid)) ; in builtins.listToAttrs (builtins.map (x: { name = x.id; value = [ (hash-of x) ]; }) drv)' var 'wd', $source_dir add_implicit_dependency runners_nix_inputs end diff --git a/executor/src/rt/supervisor/actions.rs b/executor/src/rt/supervisor/actions.rs index 2c6fc7468..60841c04d 100644 --- a/executor/src/rt/supervisor/actions.rs +++ b/executor/src/rt/supervisor/actions.rs @@ -35,7 +35,7 @@ enum ResolvedKind { /// A packaged `name:hash` runner read from the runners directory. Disk { name: symbol_table::GlobalSymbol, - hash: symbol_table::GlobalSymbol, + hash: Bytes32Hash, }, /// `chain:
::` — code blob read from a storage slot. The /// current contract (`contract`) also resolves here, pointing at its own @@ -76,9 +76,17 @@ fn resolve_runner( let resolved: runners::Id = match parsed.resolve(contract_address, state, code_slot) { runners::IdUnresolved::Contract => unreachable!("contract is resolved to chain"), runners::IdUnresolved::Builtin { name, hash } => { - let hash = if hash.as_str() == "test" || hash.as_str() == "latest" { + let hash: Bytes32Hash = if hash.as_str() == "test" { if !supervisor.shared_data.debug_mode { - log_warn!(":test/ :latest runner used in non-debug mode, this is not allowed"); + log_warn!(":test runner used in non-debug mode, this is not allowed"); + return Err(make_malformed_runner_error( + "runner id doesn't match expected format", + )); + } + runners::TEST_RUNNER_HASH + } else if hash.as_str() == "latest" { + if !supervisor.shared_data.debug_mode { + log_warn!(":latest runner used in non-debug mode, this is not allowed"); return Err(make_malformed_runner_error( "runner id doesn't match expected format", )); @@ -90,13 +98,16 @@ fn resolve_runner( "runner id doesn't match expected format", )); }; - new_latest + Bytes32Hash::from_gvm32(new_latest.as_str()) + .ok_or_else(|| make_malformed_runner_error("runner hash is not valid gvm32"))? } else { - hash + Bytes32Hash::from_gvm32(hash.as_str()) + .ok_or_else(|| make_malformed_runner_error("runner hash is not valid gvm32"))? }; - if !supervisor.runner_cache.has_in_all(name, hash) { - anyhow::bail!("runner {}:{} not found", name, hash); + let hash_sym = symbol_table::GlobalSymbol::from(hash.to_gvm32()); + if !supervisor.runner_cache.has_in_all(name, hash_sym) { + anyhow::bail!("runner {}:{} not found", name, hash_sym); } runners::Id::Builtin { name, hash } @@ -141,7 +152,7 @@ async fn get_arch( id, || async { let mut path = cache.runners_path().to_owned(); - runners::append_runner_subpath(name.as_str(), hash.as_str(), &mut path); + runners::append_runner_subpath(name.as_str(), &hash.to_gvm32(), &mut path); path.set_extension("tar"); if !path.exists() { anyhow::bail!("runner {} not found", id); diff --git a/executor/src/runners/mod.rs b/executor/src/runners/mod.rs index 90433f78e..73d7c9a07 100644 --- a/executor/src/runners/mod.rs +++ b/executor/src/runners/mod.rs @@ -52,7 +52,7 @@ pub enum IdUnresolved { pub enum Id { Builtin { name: symbol_table::GlobalSymbol, - hash: symbol_table::GlobalSymbol, + hash: Bytes32Hash, }, Chain { address: calldata::Address, @@ -97,7 +97,7 @@ impl Id { Id::Builtin { name, hash } => { let mut id = name.as_str().to_owned(); id.push(':'); - id.push_str(hash.as_str()); + id.push_str(&hash.to_gvm32()); symbol_table::GlobalSymbol::from(id) } Id::Chain { address, on, slot } => { @@ -189,16 +189,24 @@ pub fn parse_runner_id(id: &str) -> Option { }) } -/// Derives the hash component of a `custom:` runner id from its code. +/// The dev-mode magic builtin/custom runner hash. Its GVM32 form is the literal +/// string `test` padded with `0`s to 52 chars (`test0000…`), which is what shows +/// up on disk and in `all.json`/`latest.json`. The raw bytes below are exactly +/// `gvm32::decode("test0000…")`. Kept in sync with `hashToIDHash` in +/// `runners/support/default.nix`. +pub const TEST_RUNNER_HASH: Bytes32Hash = { + let mut bytes = [0u8; 32]; + bytes[0] = 0xd3; + bytes[1] = 0xb3; + bytes[2] = 0xa0; + Bytes32Hash::from_bytes(bytes) +}; + pub fn custom_runner_hash(code: &[u8]) -> Bytes32Hash { use sha3::Digest as _; let mut digest = sha3::Sha3_256::new(); digest.update(code); - let arr: [u8; 32] = digest - .finalize() - .as_slice() - .try_into() - .expect("sha3-256 is 32 bytes"); + let arr: [u8; 32] = digest.finalize().into(); Bytes32Hash::from_bytes(arr) } diff --git a/runners/support/default.nix b/runners/support/default.nix index 0f0c552bf..05b26b380 100644 --- a/runners/support/default.nix +++ b/runners/support/default.nix @@ -16,7 +16,9 @@ in rec { }; gvm32 = import ./gvm32.nix { lib = pkgs.lib; }; - hashToIDHash = hash: if hash == "test" then "test" else gvm32.encodeHex (builtins.convertHash { inherit hash; toHashFormat = "base16"; }); + # dev-mode magic hash: the literal gvm32 string "test" padded with "0"s to 52 chars + testRunnerHash = "test" + (builtins.concatStringsSep "" (builtins.genList (_: "0") 48)); + hashToIDHash = hash: if hash == "test" then testRunnerHash else gvm32.encodeHex (builtins.convertHash { inherit hash; toHashFormat = "base16"; }); package = { id, hash, baseDerivation }: { inherit id hash; diff --git a/runners/support/views/all-universal.nix b/runners/support/views/all-universal.nix index 9551d342f..c221a0376 100644 --- a/runners/support/views/all-universal.nix +++ b/runners/support/views/all-universal.nix @@ -11,7 +11,7 @@ dontBuild = true; dontFixup = true; installPhase = let - hash32 = builtins.convertHash { hash = x.hash; toHashFormat = "nix32"; }; + hash32 = builtins.head (builtins.tail (builtins.match "([^:]+):(.*)" x.uid)); result-path = "runners/${x.id}/${builtins.substring 0 2 hash32}/${builtins.substring 2 50 hash32}.tar"; in '' mkdir -p $out/$(dirname -- ${result-path}) diff --git a/runners/support/views/debug-build.nix b/runners/support/views/debug-build.nix index 560e61808..3d206db7b 100644 --- a/runners/support/views/debug-build.nix +++ b/runners/support/views/debug-build.nix @@ -8,10 +8,8 @@ let pathOfRunner = runner: let - hash32 = - if runner.hash == "test" - then "test" - else builtins.convertHash { hash = runner.hash; toHashFormat = "nix32"; }; + # the gvm32 hash id (matches `uid` / `hashToIDHash`) + hash32 = builtins.head (builtins.tail (builtins.match "([^:]+):(.*)" runner.uid)); in "${runner.id}/${builtins.substring 0 2 hash32}/${builtins.substring 2 50 hash32}.tar"; installLines = From 0a876242915f64fd8cc919284213805d468c8c25 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 00:24:16 +0900 Subject: [PATCH 042/124] =?UTF-8?q?fix(security):=20obvious=20fixes=20from?= =?UTF-8?q?=20octane=20analysis=203=20=F0=9F=94=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Five self-evident, no-tradeoff fixes from the Octane "analysis 3" pass (GVM-287); the remaining findings are false positives or need design decisions (replied on the issue): - ustar: bounds-check from_ustar payload slice and from_zip data range (checked_add + reversed-range guard). from_zip is reachable from on-chain ZIP code, where the unchecked u64 add could abort the executor. - storage: stop the read-through page cache from dropping staged pages via a modulo-wrapping staging index; insert directly when the buffer is full. - wasi random_get: propagate getrandom failure as Errno::Io in non-det mode instead of silently returning a zeroed (predictable) buffer. - llm/ollama: remove stray space in the text-mode endpoint ("/api/ generate"). - scripting pool: reject vm pool size 0 instead of panicking (div-by-zero) on first use. --- executor/src/rt/vm/storage.rs | 9 +++++-- executor/src/runners/ustar.rs | 25 ++++++++++++++++---- executor/src/wasi/preview1.rs | 1 + modules/implementation/src/llm/providers.rs | 2 +- modules/implementation/src/scripting/pool.rs | 3 +++ 5 files changed, 32 insertions(+), 8 deletions(-) diff --git a/executor/src/rt/vm/storage.rs b/executor/src/rt/vm/storage.rs index 7164df6fe..6b31d40fa 100644 --- a/executor/src/rt/vm/storage.rs +++ b/executor/src/rt/vm/storage.rs @@ -257,8 +257,13 @@ impl Storage { let mut page_data = [0u8; 32]; page_data.copy_from_slice(&buf[src_offset..src_offset + 32]); - put_to_cache[put_to_cache_count].write((page_id, page_data)); - put_to_cache_count = (put_to_cache_count + 1) % put_to_cache.len(); + if put_to_cache_count < put_to_cache.len() { + put_to_cache[put_to_cache_count].write((page_id, page_data)); + put_to_cache_count += 1; + } else { + // staging buffer full: insert directly so no read page is dropped + self.cache.insert(page_id, page_data); + } } } diff --git a/executor/src/runners/ustar.rs b/executor/src/runners/ustar.rs index e7ac91ee3..217788b7a 100644 --- a/executor/src/runners/ustar.rs +++ b/executor/src/runners/ustar.rs @@ -95,7 +95,11 @@ impl Archive { begin += file_size; begin += (BLOCK_SIZE - (begin % BLOCK_SIZE)) % BLOCK_SIZE; - let file_contents = data.slice(BLOCK_SIZE..BLOCK_SIZE + file_size); + let file_end = BLOCK_SIZE + .checked_add(file_size) + .filter(|end| *end <= data.len()) + .ok_or_else(|| anyhow::anyhow!("tar file size exceeds archive bounds"))?; + let file_contents = data.slice(BLOCK_SIZE..file_end); map_try_insert(&mut res, name, file_contents)?; } @@ -120,13 +124,24 @@ impl Archive { } let start_index = file.data_start(); - let end_index = file.data_start() + file.compressed_size(); - if end_index > bytes.len() as u64 || start_index > bytes.len() as u64 { + let compressed_size = file.compressed_size(); + let end_index = start_index.checked_add(compressed_size).ok_or_else(|| { + anyhow::anyhow!( + "file {} data_start={} compressed_size={} overflow", + file.name(), + start_index, + compressed_size + ) + })?; + if end_index > bytes.len() as u64 + || start_index > bytes.len() as u64 + || end_index < start_index + { anyhow::bail!( "file {} data_start={} compressed_size={} end_index={} bytes_len={}", file.name(), - file.data_start(), - file.compressed_size(), + start_index, + compressed_size, end_index, bytes.len() ); diff --git a/executor/src/wasi/preview1.rs b/executor/src/wasi/preview1.rs index 4ea21b9c4..3a146779f 100644 --- a/executor/src/wasi/preview1.rs +++ b/executor/src/wasi/preview1.rs @@ -1256,6 +1256,7 @@ impl generated::wasi_snapshot_preview1::WasiSnapshotPreview1 for ContextVFS<'_> // Non-deterministic mode: cryptographically secure random number generator if let Err(e) = getrandom::fill(&mut mem) { log_error!(error:err = e; "random failed"); + return Err(generated::types::Errno::Io.into()); } } diff --git a/modules/implementation/src/llm/providers.rs b/modules/implementation/src/llm/providers.rs index 0202fa204..4966ae67e 100644 --- a/modules/implementation/src/llm/providers.rs +++ b/modules/implementation/src/llm/providers.rs @@ -516,7 +516,7 @@ impl Provider for OLlama { log_warn!(extra:serde = prompt.extra; "ollama provider ignores extra body fields"); } let request = prompt.to_ollama_no_format(model); - let url = format!("{}/api/ generate", self.config.host); + let url = format!("{}/api/generate", self.config.host); log_trace!(request:serde = request, url = url; "final request body after merging extra"); let request = serde_json::to_vec(&request)?; let request = ctx.client.post(&url).body(request.clone()); diff --git a/modules/implementation/src/scripting/pool.rs b/modules/implementation/src/scripting/pool.rs index 61e56c012..0ce3ea006 100644 --- a/modules/implementation/src/scripting/pool.rs +++ b/modules/implementation/src/scripting/pool.rs @@ -24,6 +24,9 @@ pub async fn new( where F: std::future::Future>>, { + if cnt == 0 { + anyhow::bail!("vm pool size must be >= 1"); + } let mut vms = Vec::new(); for _i in 0..cnt { vms.push(Arc::new(vm_supplier().await?)); From 6194acd04d3a3f8c9a4176b6712662039d216061 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 00:39:57 +0900 Subject: [PATCH 043/124] =?UTF-8?q?feat(webdriver):=20SSRF=20guard=20via?= =?UTF-8?q?=20CDP=20request=20interception=20=F0=9F=94=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Intercept every request Chrome makes (navigation, sub-resources, redirect hops) and abort those whose host resolves to a non-globally-routable address (loopback, RFC1918, link-local incl. 169.254/16, CGNAT, IPv6 ULA/link-local, v4-mapped). Fails closed: a host is blocked if any resolved address is private. Blocked navigations surface as HTTP 403. --- modules/webdriver/src/prj/src/index.ts | 6 + modules/webdriver/src/prj/src/ssrf.ts | 244 +++++++++++++++++++++++++ 2 files changed, 250 insertions(+) create mode 100644 modules/webdriver/src/prj/src/ssrf.ts diff --git a/modules/webdriver/src/prj/src/index.ts b/modules/webdriver/src/prj/src/index.ts index d5bb5e28c..37ce5b818 100644 --- a/modules/webdriver/src/prj/src/index.ts +++ b/modules/webdriver/src/prj/src/index.ts @@ -4,6 +4,7 @@ import { Command } from 'commander'; import * as logger from './logging.js'; import * as chromeBrowser from './browser/chrome.js'; +import * as ssrf from './ssrf.js'; import { envDurationMs, envInt, formatDurationMs } from './duration.js'; interface NavigationOptions { @@ -66,6 +67,8 @@ function getNavigationErrorStatus(error: any): number { return 495; // SSL Certificate Error } else if (error.message?.includes('net::ERR_INTERNET_DISCONNECTED')) { return 503; // Service Unavailable + } else if (error.message?.includes('net::ERR_BLOCKED_BY_CLIENT')) { + return 403; // Forbidden (SSRF guard) } return STATUS_I_AM_A_TEAPOT; // Unknown error } @@ -81,6 +84,8 @@ function getNavigationErrorMessage(error: any): string { return 'SSL certificate error'; } else if (error.message?.includes('net::ERR_INTERNET_DISCONNECTED')) { return 'No internet connection'; + } else if (error.message?.includes('net::ERR_BLOCKED_BY_CLIENT')) { + return 'Blocked by SSRF guard: address not allowed'; } return `Navigation error: ${error.message || 'Unknown error'}`; } @@ -238,6 +243,7 @@ async function renderPageWithBrowser( const page = await browserInstance.newPage(); try { + await ssrf.installSsrfGuard(page); page.setViewport({ width: 1920 / 2, height: 1080 / 2 }); return await withHeapMonitor(page, maxPageHeapMB, async () => { diff --git a/modules/webdriver/src/prj/src/ssrf.ts b/modules/webdriver/src/prj/src/ssrf.ts new file mode 100644 index 000000000..354878b14 --- /dev/null +++ b/modules/webdriver/src/prj/src/ssrf.ts @@ -0,0 +1,244 @@ +import * as dns from 'node:dns/promises'; +import * as net from 'node:net'; +import type * as pup from 'puppeteer-core'; +import * as logger from './logging.js'; + +/** + * SSRF guard for the webdriver. + * + * Chrome resolves DNS and follows redirects itself, so it never passes through + * any host-side filter. Without this guard a contract could point an otherwise + * valid public URL (or one of the page's sub-resources) at an internal address + * such as cloud metadata (169.254.169.254), loopback or an RFC1918 host. + * + * We intercept every request the page makes (top-level navigation, + * sub-resources and each redirect hop), resolve the host ourselves and abort + * the request when any resolved address is not globally routable. + * + * NOTE: resolution happens here while Chrome connects separately, so a low-TTL + * attacker controlling DNS could in theory return a routable address to us and + * a private one to Chrome. We mitigate by failing closed: if *any* address a + * host resolves to is private, the host is blocked outright. + */ + +function parseIPv4(ip: string): [number, number, number, number] | null { + const parts = ip.split('.'); + if (parts.length !== 4) { + return null; + } + const nums: number[] = []; + for (const part of parts) { + if (!/^\d{1,3}$/.test(part)) { + return null; + } + const n = Number(part); + if (n > 255) { + return null; + } + nums.push(n); + } + return [nums[0]!, nums[1]!, nums[2]!, nums[3]!]; +} + +/** Whether an IPv4 address is not safe to connect to (not globally routable). */ +function ipv4IsBad(ip: string): boolean { + const octets = parseIPv4(ip); + if (octets === null) { + return true; // unparseable => fail closed + } + const [a, b, c] = octets; + return ( + a === 0 || // 0.0.0.0/8 "this" network + a === 10 || // 10.0.0.0/8 private + a === 127 || // 127.0.0.0/8 loopback + (a === 169 && b === 254) || // 169.254.0.0/16 link-local + (a === 172 && b >= 16 && b <= 31) || // 172.16.0.0/12 private + (a === 192 && b === 168) || // 192.168.0.0/16 private + (a === 100 && b >= 64 && b <= 127) || // 100.64.0.0/10 CGNAT + (a === 192 && b === 0 && c === 2) || // 192.0.2.0/24 documentation + (a === 198 && b === 51 && c === 100) || // 198.51.100.0/24 documentation + (a === 203 && b === 0 && c === 113) || // 203.0.113.0/24 documentation + a >= 224 // 224.0.0.0/3 multicast + reserved + broadcast + ); +} + +function parseIPv6(ip: string): number[] | null { + const withoutZone = ip.split('%')[0] ?? ''; + const halves = withoutZone.split('::'); + if (halves.length > 2) { + return null; + } + + const parseGroups = (segment: string): number[] | null => { + if (segment === '') { + return []; + } + const parts = segment.split(':'); + const groups: number[] = []; + for (let i = 0; i < parts.length; i++) { + const part = parts[i]!; + if (part.includes('.')) { + // embedded IPv4 is only valid as the final element + if (i !== parts.length - 1) { + return null; + } + const octets = parseIPv4(part); + if (octets === null) { + return null; + } + const [a, b, c, d] = octets; + groups.push((a << 8) | b); + groups.push((c << 8) | d); + } else { + if (!/^[0-9a-fA-F]{1,4}$/.test(part)) { + return null; + } + groups.push(parseInt(part, 16)); + } + } + return groups; + }; + + if (halves.length === 1) { + const groups = parseGroups(halves[0]!); + if (groups === null || groups.length !== 8) { + return null; + } + return groups; + } + + const head = parseGroups(halves[0]!); + const tail = parseGroups(halves[1]!); + if (head === null || tail === null) { + return null; + } + const missing = 8 - head.length - tail.length; + if (missing < 1) { + return null; // "::" must stand for at least one zero group + } + return [...head, ...new Array(missing).fill(0), ...tail]; +} + +/** Whether an IPv6 address is not safe to connect to (not globally routable). */ +function ipv6IsBad(ip: string): boolean { + const groups = parseIPv6(ip); + if (groups === null || groups.length !== 8) { + return true; // fail closed + } + + // an IPv4-mapped address (::ffff:a.b.c.d) is only as safe as its IPv4 part + if ( + groups[0] === 0 && + groups[1] === 0 && + groups[2] === 0 && + groups[3] === 0 && + groups[4] === 0 && + groups[5] === 0xffff + ) { + const g6 = groups[6]!; + const g7 = groups[7]!; + const v4 = `${g6 >> 8}.${g6 & 0xff}.${g7 >> 8}.${g7 & 0xff}`; + return ipv4IsBad(v4); + } + + if (groups.every((g) => g === 0)) { + return true; // :: unspecified + } + if (groups.slice(0, 7).every((g) => g === 0) && groups[7] === 1) { + return true; // ::1 loopback + } + + const first = groups[0]!; + return ( + (first & 0xfe00) === 0xfc00 || // fc00::/7 unique-local + (first & 0xffc0) === 0xfe80 || // fe80::/10 link-local + (first & 0xff00) === 0xff00 // ff00::/8 multicast + ); +} + +/** Whether a resolved address must not be connected to (SSRF guard). */ +export function ipIsBad(ip: string): boolean { + switch (net.isIP(ip)) { + case 4: + return ipv4IsBad(ip); + case 6: + return ipv6IsBad(ip); + default: + return true; // not a bare IP => fail closed + } +} + +/** Resolve a URL host to its addresses; IP literals resolve to themselves. */ +async function resolveHost(host: string): Promise { + const stripped = + host.startsWith('[') && host.endsWith(']') ? host.slice(1, -1) : host; + if (net.isIP(stripped) !== 0) { + return [stripped]; + } + const results = await dns.lookup(stripped, { all: true }); + return results.map((r) => r.address); +} + +// Schemes that perform no network access and are always allowed. +const NETWORKLESS_SCHEMES = new Set(['data:', 'blob:', 'about:']); +// Schemes that go to a host and must be checked. +const NETWORK_SCHEMES = new Set(['http:', 'https:', 'ws:', 'wss:']); + +async function isUrlAllowed(rawUrl: string): Promise { + let parsed: URL; + try { + parsed = new URL(rawUrl); + } catch { + return false; + } + if (NETWORKLESS_SCHEMES.has(parsed.protocol)) { + return true; + } + if (!NETWORK_SCHEMES.has(parsed.protocol)) { + return false; // file:, ftp:, chrome:, ... + } + let addrs: string[]; + try { + addrs = await resolveHost(parsed.hostname); + } catch { + return false; // resolution failure => block + } + if (addrs.length === 0) { + return false; + } + // fail closed: block if *any* resolved address is non-globally-routable + return !addrs.some(ipIsBad); +} + +/** + * Enable request interception on `page` and abort every request whose target + * resolves to a non-globally-routable address. + */ +export async function installSsrfGuard(page: pup.Page): Promise { + await page.setRequestInterception(true); + page.on('request', (request) => { + void (async () => { + const url = request.url(); + let allowed: boolean; + try { + allowed = await isUrlAllowed(url); + } catch { + allowed = false; + } + try { + if (allowed) { + await request.continue(); + } else { + logger.log('warn', 'ssrf guard blocked request', { url }); + await request.abort('blockedbyclient'); + } + } catch (e) { + // the request may already be resolved or the page may be gone + logger.log('debug', 'ssrf guard could not finalize request', { + url, + error: (e as Error).message, + }); + } + })(); + }); +} From 74dbb06c5012c13805a789a7f70119ef9e153a90 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 00:41:39 +0900 Subject: [PATCH 044/124] =?UTF-8?q?feat(webdriver):=20configurable=20Chrom?= =?UTF-8?q?e=20launch=20via=20env=20vars=20=F0=9F=94=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GVM_WEBDRIVER_CHROME_EXECUTABLE overrides the chromium path, GVM_WEBDRIVER_CHROME_HEADLESS toggles headless mode, and GVM_WEBDRIVER_CHROME_ARGS appends extra launch flags (whitespace-split, or a JSON array when flags contain spaces). Adds envStr/envBool/envStrList helpers. --- .../webdriver/src/prj/src/browser/chrome.ts | 45 +++++++++---- modules/webdriver/src/prj/src/duration.ts | 66 +++++++++++++++++++ 2 files changed, 97 insertions(+), 14 deletions(-) diff --git a/modules/webdriver/src/prj/src/browser/chrome.ts b/modules/webdriver/src/prj/src/browser/chrome.ts index 90961b80a..6fc10a299 100644 --- a/modules/webdriver/src/prj/src/browser/chrome.ts +++ b/modules/webdriver/src/prj/src/browser/chrome.ts @@ -2,7 +2,14 @@ import puppeteer, * as pup from 'puppeteer-core'; import * as logger from '../logging.js'; import * as util from 'util'; import * as child_process from 'child_process'; -import { envDurationMs, envInt, formatDurationMs } from '../duration.js'; +import { + envBool, + envDurationMs, + envInt, + envStr, + envStrList, + formatDurationMs, +} from '../duration.js'; import type * as browser from './index.js'; class BrowserHolder { @@ -59,21 +66,31 @@ const RENDERER_PROCESS_LIMIT = envInt( 4, ); +const CHROME_EXECUTABLE = envStr( + 'GVM_WEBDRIVER_CHROME_EXECUTABLE', + '/usr/bin/chromium', +); +const CHROME_HEADLESS = envBool('GVM_WEBDRIVER_CHROME_HEADLESS', true); +// Extra flags appended to the defaults below. See `envStrList` for the format. +const CHROME_EXTRA_ARGS = envStrList('GVM_WEBDRIVER_CHROME_ARGS', []); + async function newBrowser(): Promise { + const args = [ + '--no-sandbox', + '--disable-dev-shm-usage', + '--disable-accelerated-2d-canvas', + '--no-first-run', + '--no-zygote', + '--disable-gpu', + '--enable-precise-memory-info', + `--js-flags=--max-old-space-size=${RENDERER_MAX_OLD_SPACE_MB}`, + `--renderer-process-limit=${RENDERER_PROCESS_LIMIT}`, + ...CHROME_EXTRA_ARGS, + ]; const realBrowser = await puppeteer.launch({ - headless: true, - args: [ - '--no-sandbox', - '--disable-dev-shm-usage', - '--disable-accelerated-2d-canvas', - '--no-first-run', - '--no-zygote', - '--disable-gpu', - '--enable-precise-memory-info', - `--js-flags=--max-old-space-size=${RENDERER_MAX_OLD_SPACE_MB}`, - `--renderer-process-limit=${RENDERER_PROCESS_LIMIT}`, - ], - executablePath: '/usr/bin/chromium', + headless: CHROME_HEADLESS, + args, + executablePath: CHROME_EXECUTABLE, }); logger.log('info', 'created new raw browser', { diff --git a/modules/webdriver/src/prj/src/duration.ts b/modules/webdriver/src/prj/src/duration.ts index 720fdfb22..ec7ddaad5 100644 --- a/modules/webdriver/src/prj/src/duration.ts +++ b/modules/webdriver/src/prj/src/duration.ts @@ -66,3 +66,69 @@ export function envInt(envName: string, defaultValue: number): number { }); return result; } + +export function envStr(envName: string, defaultValue: string): string { + const raw = process.env[envName]; + const value = raw !== undefined && raw !== '' ? raw : defaultValue; + logger.log('info', 'env', { + name: envName, + raw: raw ?? null, + value, + default: defaultValue, + }); + return value; +} + +const ENV_BOOL_TRUE = ['1', 'true', 'yes', 'on']; +const ENV_BOOL_FALSE = ['0', 'false', 'no', 'off']; + +export function envBool(envName: string, defaultValue: boolean): boolean { + const raw = process.env[envName]; + let value = defaultValue; + if (raw !== undefined && raw !== '') { + const norm = raw.trim().toLowerCase(); + if (ENV_BOOL_TRUE.includes(norm)) { + value = true; + } else if (ENV_BOOL_FALSE.includes(norm)) { + value = false; + } else { + throw new Error(`invalid boolean for env ${envName}: "${raw}"`); + } + } + logger.log('info', 'env', { + name: envName, + raw: raw ?? null, + value, + default: defaultValue, + }); + return value; +} + +/** + * Parse a list of strings from an env var. A value starting with `[` is parsed + * as a JSON array (use this when arguments contain spaces); otherwise the value + * is split on whitespace. + */ +export function envStrList(envName: string, defaultValue: string[]): string[] { + const raw = process.env[envName]; + let value = defaultValue; + const trimmed = raw?.trim() ?? ''; + if (trimmed !== '') { + if (trimmed.startsWith('[')) { + const parsed: unknown = JSON.parse(trimmed); + if (!Array.isArray(parsed) || parsed.some((x) => typeof x !== 'string')) { + throw new Error(`invalid string list for env ${envName}: "${raw}"`); + } + value = parsed as string[]; + } else { + value = trimmed.split(/\s+/); + } + } + logger.log('info', 'env', { + name: envName, + raw: raw ?? null, + value, + default: defaultValue, + }); + return value; +} From 51e675b5ca253b5cc12ba960ecb629837e6a5ede Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 00:48:37 +0900 Subject: [PATCH 045/124] =?UTF-8?q?docs(spec):=20random=5Fget=20fails=20wi?= =?UTF-8?q?th=20errno::io=20on=20RNG=20failure=20in=20non-det=20mode=20?= =?UTF-8?q?=F0=9F=93=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The wasip1 spec previously allowed an "optional fallback to pseudo-random numbers" when the secure source is unavailable; that sanctioned the silent zeroed/predictable fallback flagged by octane analysis 3 (warning 10). Spec now mandates failing with errno::io instead, matching the executor fix in commit 7f6eef25 (executor/src/wasi/preview1.rs random_get). --- doc/website/src/spec/02-execution-environment/02-wasip1.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/website/src/spec/02-execution-environment/02-wasip1.rst b/doc/website/src/spec/02-execution-environment/02-wasip1.rst index 1fd508363..beeabe004 100644 --- a/doc/website/src/spec/02-execution-environment/02-wasip1.rst +++ b/doc/website/src/spec/02-execution-environment/02-wasip1.rst @@ -144,8 +144,10 @@ runs with identical stdin see the same ``random_get`` stream, while differing in produce diverging streams. Non-deterministic randomness MUST be obtained via :ref:`gvm-def-non-det-mode` calls. -Non-deterministic mode: cryptographically secure random number generator, -with optional fallback to pseudo-random numbers, if secure source is exhausted or unavailable. +Non-deterministic mode: a cryptographically secure random number generator. If the +secure source is unavailable or fails, ``random_get`` MUST fail with ``errno::io`` +instead of falling back to a predictable stream (pseudo-random or zeroed output). A +caller that wants a graceful fallback must handle that error explicitly. ``proc_exit`` Function ~~~~~~~~~~~~~~~~~~~~~~ From 12c3e144419d75c12a304e2b40c88fa269d6ec00 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 01:07:45 +0900 Subject: [PATCH 046/124] =?UTF-8?q?fix(webdriver):=20prevent=20overlapping?= =?UTF-8?q?=20browser=20rotations=20=F0=9F=94=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace setInterval with a self-rescheduling setTimeout that arms the next rotation check only after the current one settles (in finally). Eliminates the overlap where two async ticks read the same holder before either swaps it, which could orphan a freshly launched browser (process leak) or close one still serving a render. Also avoids interval backlog under sustained load. Fixes octane analysis 3, warning 11 (GVM-287). --- .../webdriver/src/prj/src/browser/chrome.ts | 136 ++++++++++-------- 1 file changed, 79 insertions(+), 57 deletions(-) diff --git a/modules/webdriver/src/prj/src/browser/chrome.ts b/modules/webdriver/src/prj/src/browser/chrome.ts index 6fc10a299..6d618df91 100644 --- a/modules/webdriver/src/prj/src/browser/chrome.ts +++ b/modules/webdriver/src/prj/src/browser/chrome.ts @@ -146,66 +146,88 @@ class ChromeBrowserManager implements browser.Manager { private constructor(holder: BrowserHolder) { this.holder = holder; this.used = false; - setInterval(async () => { - const used = this.used; - const lastMemoryMB = this.lastMemoryMB; - const old = this.holder; - const proc = old.browser.process(); - const pid = proc?.pid; - let usedRAMMB = pid ? await getTotalRssMB(pid) : await getSelfRssMB(); - this.lastMemoryMB = usedRAMMB; - - let memoryDeltaMB = lastMemoryMB !== null ? usedRAMMB - lastMemoryMB : 0; - - const reasons: string[] = []; - - if ( - initialMemoryMB && - usedRAMMB > initialMemoryMB + ROTATION_ABSOLUTE_THRESHOLD_MB - ) { - reasons.push( - `absolute memory ${usedRAMMB.toFixed(0)}MB exceeds initial ${initialMemoryMB.toFixed(0)}MB + ${ROTATION_ABSOLUTE_THRESHOLD_MB}MB`, - ); - } - - if (!used && memoryDeltaMB > ROTATION_IDLE_DELTA_MB) { - reasons.push( - `idle memory grew by ${memoryDeltaMB.toFixed(0)}MB (threshold ${ROTATION_IDLE_DELTA_MB}MB)`, - ); - } - - if ( - ROTATION_AT_LEAST_MS > 0 && - Date.now() - this.lastRotationTime >= ROTATION_AT_LEAST_MS - ) { - reasons.push( - `age ${formatDurationMs(Date.now() - this.lastRotationTime)} exceeds max ${formatDurationMs(ROTATION_AT_LEAST_MS)}`, - ); - } - - logger.log('info', 'browser rotation check', { - shouldRotate: reasons.length > 0, - reasons, - used, - usedRAMMB, - memoryDeltaMB, - initialMemoryMB, - lastRotationAgo: formatDurationMs(Date.now() - this.lastRotationTime), - }); - - if (reasons.length === 0) { - return; - } - - const newB = await newBrowser(); - this.holder = newB; - this.lastMemoryMB = null; - this.used = false; - this.lastRotationTime = Date.now(); - await old.close(); + this.scheduleRotationCheck(); + } + + /** + * Arm the next rotation check. Uses a self-rescheduling timeout instead of + * setInterval so the next check is only scheduled once the current one has + * fully settled (in `finally`). This structurally prevents overlapping + * rotations from interleaving holder swaps / closes — which could otherwise + * orphan a freshly launched browser (process leak) or close one still + * serving a render — and avoids interval backlog under sustained load. + */ + private scheduleRotationCheck(): void { + setTimeout(() => { + void this.rotationCheck() + .catch((error) => { + logger.log('error', 'browser rotation check failed', { error }); + }) + .finally(() => { + this.scheduleRotationCheck(); + }); }, ROTATION_CHECK_INTERVAL_MS); } + private async rotationCheck(): Promise { + const used = this.used; + const lastMemoryMB = this.lastMemoryMB; + const old = this.holder; + const proc = old.browser.process(); + const pid = proc?.pid; + let usedRAMMB = pid ? await getTotalRssMB(pid) : await getSelfRssMB(); + this.lastMemoryMB = usedRAMMB; + + let memoryDeltaMB = lastMemoryMB !== null ? usedRAMMB - lastMemoryMB : 0; + + const reasons: string[] = []; + + if ( + initialMemoryMB && + usedRAMMB > initialMemoryMB + ROTATION_ABSOLUTE_THRESHOLD_MB + ) { + reasons.push( + `absolute memory ${usedRAMMB.toFixed(0)}MB exceeds initial ${initialMemoryMB.toFixed(0)}MB + ${ROTATION_ABSOLUTE_THRESHOLD_MB}MB`, + ); + } + + if (!used && memoryDeltaMB > ROTATION_IDLE_DELTA_MB) { + reasons.push( + `idle memory grew by ${memoryDeltaMB.toFixed(0)}MB (threshold ${ROTATION_IDLE_DELTA_MB}MB)`, + ); + } + + if ( + ROTATION_AT_LEAST_MS > 0 && + Date.now() - this.lastRotationTime >= ROTATION_AT_LEAST_MS + ) { + reasons.push( + `age ${formatDurationMs(Date.now() - this.lastRotationTime)} exceeds max ${formatDurationMs(ROTATION_AT_LEAST_MS)}`, + ); + } + + logger.log('info', 'browser rotation check', { + shouldRotate: reasons.length > 0, + reasons, + used, + usedRAMMB, + memoryDeltaMB, + initialMemoryMB, + lastRotationAgo: formatDurationMs(Date.now() - this.lastRotationTime), + }); + + if (reasons.length === 0) { + return; + } + + const newB = await newBrowser(); + this.holder = newB; + this.lastMemoryMB = null; + this.used = false; + this.lastRotationTime = Date.now(); + await old.close(); + } + getBrowser(): browser.Handle { this.holder.counter++; this.used = true; From 920453eeb9390cc629d4eb5161c87e78a4a26aca Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 01:16:02 +0900 Subject: [PATCH 047/124] =?UTF-8?q?fix(web):=20reject=20HTTPS->HTTP=20down?= =?UTF-8?q?grade=20redirects=20=F0=9F=94=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit redirect_policy now refuses to follow a redirect that downgrades an HTTPS hop to plaintext HTTP. Following one would carry a request signature (and other headers) onto a cleartext hop observable and replayable by on-path attackers. Independent of receiver behavior. Part of octane analysis 3, warning 9 (GVM-287), option B. --- modules/implementation/src/common/mod.rs | 31 +++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/modules/implementation/src/common/mod.rs b/modules/implementation/src/common/mod.rs index 8cf6a80a9..bd31a41da 100644 --- a/modules/implementation/src/common/mod.rs +++ b/modules/implementation/src/common/mod.rs @@ -803,6 +803,11 @@ const MAX_REDIRECTS: usize = 10; /// This policy closes that hole by rejecting redirect hops whose host is a /// non-globally-routable IP literal; hostname targets keep being filtered by the /// resolver when the next hop connects. +/// +/// It also rejects HTTPS->HTTP downgrade redirects: following one would carry +/// any request signature (which does not bind the scheme tightly enough at all +/// receivers) onto a plaintext hop observable and replayable by on-path +/// attackers. pub fn redirect_policy() -> reqwest::redirect::Policy { reqwest::redirect::Policy::custom(|attempt| { if attempt.previous().len() >= MAX_REDIRECTS { @@ -816,13 +821,33 @@ pub fn redirect_policy() -> reqwest::redirect::Policy { }; if bad { log_warn!(url = attempt.url().as_str(); "redirect to non-globally-routable IP-literal rejected"); - attempt.error(NoRoutableAddress) - } else { - attempt.follow() + return attempt.error(NoRoutableAddress); + } + let downgrade = attempt + .previous() + .last() + .is_some_and(|prev| prev.scheme() == "https" && attempt.url().scheme() == "http"); + if downgrade { + log_warn!(url = attempt.url().as_str(); "HTTPS->HTTP downgrade redirect rejected"); + return attempt.error(SchemeDowngrade); } + attempt.follow() }) } +/// Error returned by [`redirect_policy`] when a redirect would downgrade an +/// HTTPS hop to plaintext HTTP. +#[derive(Debug)] +struct SchemeDowngrade; + +impl std::fmt::Display for SchemeDowngrade { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str("refusing to follow HTTPS->HTTP downgrade redirect") + } +} + +impl std::error::Error for SchemeDowngrade {} + /// A client whose resolver drops non-globally-routable addresses (see /// [`FilteringResolver`]) and whose redirect policy rejects non-routable /// IP-literal hops (see [`redirect_policy`]). For contract-controlled web URLs. From a6e946a8c6b208cbe82bed647a0a1337b428ec65 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 01:16:10 +0900 Subject: [PATCH 048/124] =?UTF-8?q?fix(web):=20bind=20@scheme=20in=20reque?= =?UTF-8?q?st=20signatures=20=F0=9F=94=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add @scheme to the always-signed RFC 9421 component set (and resolve it in rfc9421_get_component_value) so a signature is no longer valid across http:// and https:// for the same authority/path. Updated signing unit tests. Part of octane analysis 3, warning 9 (GVM-287), option A. NOTE: this changes the signature base, so receivers must be updated in lockstep to reconstruct @scheme — the live-server signing test fails until the receiver supports it. --- modules/implementation/src/scripting/ctx/signing.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/implementation/src/scripting/ctx/signing.rs b/modules/implementation/src/scripting/ctx/signing.rs index 1fc449e04..6c4c303f2 100644 --- a/modules/implementation/src/scripting/ctx/signing.rs +++ b/modules/implementation/src/scripting/ctx/signing.rs @@ -9,6 +9,7 @@ const SIGN_ALGORITHM: &str = "ES256K"; const ALWAYS_SIGN: &[&str] = &[ "@method", + "@scheme", "@authority", "@path", "genlayer-node-address", @@ -110,6 +111,7 @@ impl Request { fn rfc9421_get_component_value(&self, component: &str) -> Result { match component { "@method" => Ok(format!("{:?}", self.method)), + "@scheme" => Ok(self.url.scheme().to_lowercase()), "@authority" => Ok(self.url.authority().to_lowercase()), "@path" => Ok(self.url.path().to_owned()), "@query" => self @@ -334,17 +336,18 @@ mod tests { assert_eq!( signature_params, - r#"("@method" "@authority" "@path" "genlayer-node-address" "genlayer-tx-id" "genlayer-salt" "@query");created=1750171014;alg="ES256K""# + r#"("@method" "@scheme" "@authority" "@path" "genlayer-node-address" "genlayer-tx-id" "genlayer-salt" "@query");created=1750171014;alg="ES256K""# ); let base = r#" "@method": GET +"@scheme": https "@authority": example.com "@path": /foo "genlayer-node-address": test_address "genlayer-tx-id": test_tx_id "genlayer-salt": "@query": ?a=b -"@signature-params": ("@method" "@authority" "@path" "genlayer-node-address" "genlayer-tx-id" "genlayer-salt" "@query");created=1750171014;alg="ES256K" +"@signature-params": ("@method" "@scheme" "@authority" "@path" "genlayer-node-address" "genlayer-tx-id" "genlayer-salt" "@query");created=1750171014;alg="ES256K" "#; let base = base.trim(); assert_eq!(signature_base.trim(), base); @@ -393,17 +396,18 @@ mod tests { assert_eq!( signature_params, - r#"("@method" "@authority" "@path" "genlayer-node-address" "genlayer-tx-id" "genlayer-salt" "content-digest");created=1750171014;alg="ES256K""# + r#"("@method" "@scheme" "@authority" "@path" "genlayer-node-address" "genlayer-tx-id" "genlayer-salt" "content-digest");created=1750171014;alg="ES256K""# ); let base = r#" "@method": POST +"@scheme": https "@authority": example.com "@path": /pst "genlayer-node-address": test_address "genlayer-tx-id": test_tx_id "genlayer-salt": "content-digest": sha-256=:Y++zFe1xzH5aH8ICQ0uzrsIJHng4cH4UigF/rrt0ZP4=: -"@signature-params": ("@method" "@authority" "@path" "genlayer-node-address" "genlayer-tx-id" "genlayer-salt" "content-digest");created=1750171014;alg="ES256K" +"@signature-params": ("@method" "@scheme" "@authority" "@path" "genlayer-node-address" "genlayer-tx-id" "genlayer-salt" "content-digest");created=1750171014;alg="ES256K" "#; let base = base.trim(); assert_eq!(signature_base.trim(), base); From 7e50f05768251951842471c78b9d5def603db9f5 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 01:20:20 +0900 Subject: [PATCH 049/124] =?UTF-8?q?fix(web):=20normalize=20headers=20on=20?= =?UTF-8?q?unsigned=20requests=20too=20=F0=9F=94=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit normalize_headers (drops host, content-length, genlayer-*, @-prefixed) used to run only on the signing path, so unsigned requests could forge Host/genlayer-* headers for vhost pivoting or identity spoofing. into_reqwest now normalizes every request, guarded by a headers_normalized flag so the signed path doesn't re-strip the genlayer-* headers it legitimately adds after normalizing. Fixes octane analysis 3, warning 8 (GVM-287), option A. --- .../implementation/src/scripting/ctx/req.rs | 21 ++++++++++++++++++- .../src/scripting/ctx/signing.rs | 3 +++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/modules/implementation/src/scripting/ctx/req.rs b/modules/implementation/src/scripting/ctx/req.rs index 02eb9a5b2..bc5b2632a 100644 --- a/modules/implementation/src/scripting/ctx/req.rs +++ b/modules/implementation/src/scripting/ctx/req.rs @@ -39,6 +39,13 @@ pub struct Request { /// one. Set by the web module for hosts in `always_allow_hosts`. #[serde(default = "default_false")] pub unfiltered: bool, + + /// Set once `normalize_headers` has run. Lets `into_reqwest` normalize every + /// request exactly once without re-stripping the `genlayer-*` headers the + /// signing path legitimately adds after normalizing. Not part of the wire + /// format. + #[serde(skip)] + pub headers_normalized: bool, } const DROP_HEADERS: &[&str] = &[ @@ -67,12 +74,22 @@ impl Request { self.headers.insert(lower_k, v); } + + self.headers_normalized = true; } pub fn into_reqwest( - self, + mut self, client: &reqwest::Client, ) -> Result { + // Drop forbidden/forged headers (host, content-length, genlayer-*, @*) + // on every request. The signing path normalizes earlier (before adding + // the legitimate genlayer-* headers), so the flag keeps us from + // stripping those back out here. + if !self.headers_normalized { + self.normalize_headers(); + } + let method = match self.method { web_iface::RequestMethod::GET => reqwest::Method::GET, web_iface::RequestMethod::POST => reqwest::Method::POST, @@ -141,6 +158,7 @@ mod tests { response_body_max_size: Some(1024), timeout: None, unfiltered: false, + headers_normalized: false, }; let body_size_limit = req.response_body_max_size.unwrap_or(usize::MAX); @@ -180,6 +198,7 @@ mod tests { response_body_max_size: Some(1024), timeout: None, unfiltered: false, + headers_normalized: false, }; let body_size_limit = 1024; diff --git a/modules/implementation/src/scripting/ctx/signing.rs b/modules/implementation/src/scripting/ctx/signing.rs index 6c4c303f2..43c315360 100644 --- a/modules/implementation/src/scripting/ctx/signing.rs +++ b/modules/implementation/src/scripting/ctx/signing.rs @@ -308,6 +308,7 @@ mod tests { response_body_max_size: None, timeout: None, unfiltered: false, + headers_normalized: false, }; req.normalize_headers(); @@ -368,6 +369,7 @@ mod tests { response_body_max_size: None, timeout: None, unfiltered: false, + headers_normalized: false, }; req.normalize_headers(); @@ -430,6 +432,7 @@ mod tests { response_body_max_size: None, timeout: None, unfiltered: false, + headers_normalized: false, }; let part = CtxPart { From f647a4f38cb4a582f69333a91ad5387f6ebef329 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 01:24:37 +0900 Subject: [PATCH 050/124] =?UTF-8?q?fix(install):=20safe=20executor=20tar?= =?UTF-8?q?=20extraction=20+=20optional=20integrity=20check=20=F0=9F=94=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit extractall now uses filter='data', rejecting absolute/.. paths and unsafe link/device members so a crafted archive can't write outside genvm_root_dir. Also verify the decompressed .tar against an expected hash before extracting, when one is present in the manifest's executor_versions entry (hash is over the .tar, matching runner_check_bytes, not the .tar.xz). No executor hash is published today, so it warns rather than fails; add a 'hash' field to enforce. Fixes octane analysis 3, vulnerability 30 (GVM-287). --- .../lib/python/post-install/__main__.py | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/modules/install/lib/python/post-install/__main__.py b/modules/install/lib/python/post-install/__main__.py index 75ee22ab0..71d45a30d 100644 --- a/modules/install/lib/python/post-install/__main__.py +++ b/modules/install/lib/python/post-install/__main__.py @@ -519,7 +519,29 @@ def process_executor_version(executor_version: str): }, ) tar_data = lzma.decompress(tar_xz_data) - tarfile.TarFile.open(fileobj=io.BytesIO(tar_data)).extractall(path=genvm_root_dir) + + # Integrity check before extraction. The expected hash, when present + # in the manifest, is taken over the decompressed `.tar` (matching the + # runner convention in runner_check_bytes), not the `.tar.xz`. No + # executor hash is published yet, so this currently warns instead of + # failing; add a `hash` field to the manifest's executor_versions entry + # to enforce it. + expected_hash = ( + manifest.get('executor_versions', {}).get(executor_version, {}).get('hash') + ) + if expected_hash is not None: + if not runner_check_bytes(tar_data, expected_hash): + raise ValueError(f'hash mismatch for executor {executor_version}') + else: + logger.warning( + f'no integrity hash for executor {executor_version}; skipping verification' + ) + + # filter='data' rejects absolute / `..` paths and unsafe link and device + # members, preventing writes outside genvm_root_dir (tar path-traversal / + # link-abuse). + with tarfile.TarFile.open(fileobj=io.BytesIO(tar_data)) as tar: + tar.extractall(path=genvm_root_dir, filter='data') if not executor_executable.exists(): if args.error_on_missing_executor: logger.error(f'Executor path {executor_executable} does not exist') From 0a3a94bae0426e5bdb20a72538cbadb233d22b47 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 01:26:01 +0900 Subject: [PATCH 051/124] =?UTF-8?q?fix(web):=20bound=20signer=20preflight?= =?UTF-8?q?=20with=20a=20default=20timeout=20=F0=9F=94=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The RFC9421 signer preflight POST had no per-request timeout and fell back to the reqwest client default (~5 min), so a slow or stalled signer could tie up a web-module task for minutes (DoS). Apply a 60s timeout to the preflight. Fixes octane analysis 3, vulnerability 26 (GVM-287). --- modules/implementation/src/scripting/ctx/signing.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/implementation/src/scripting/ctx/signing.rs b/modules/implementation/src/scripting/ctx/signing.rs index 43c315360..2cf6f6a69 100644 --- a/modules/implementation/src/scripting/ctx/signing.rs +++ b/modules/implementation/src/scripting/ctx/signing.rs @@ -7,6 +7,11 @@ use genvm_modules_interfaces::GenericValue; const SIGN_ALGORITHM: &str = "ES256K"; +/// Per-request timeout for the signer preflight POST. Without it the request +/// falls back to the reqwest client default (~5 min), so a slow or stalled +/// signer would tie up a web-module task for minutes. +const SIGN_PREFLIGHT_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(60); + const ALWAYS_SIGN: &[&str] = &[ "@method", "@scheme", @@ -59,6 +64,7 @@ impl Request { let mut sign_request = ctx .client_unfiltered .post(sign_url) + .timeout(SIGN_PREFLIGHT_TIMEOUT) .body(signature_base.clone()); //let signature_base_hashed = ring::digest::digest(&ring::digest::SHA256, signature_base.as_bytes()); From 7226d24b8ee46edfbb5410ccc7e464b8d41c9fea Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 01:42:39 +0900 Subject: [PATCH 052/124] =?UTF-8?q?fix(llm):=20bound=20provider=20response?= =?UTF-8?q?=20body=20size=20to=20cap=20OOM=20DoS=20=F0=9F=94=92=EF=B8=8F?= =?UTF-8?q?=F0=9F=90=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/implementation/src/llm/prompt.rs | 4 ++++ modules/implementation/src/llm/providers.rs | 18 +++++++++--------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/modules/implementation/src/llm/prompt.rs b/modules/implementation/src/llm/prompt.rs index 305489054..4ca10f281 100644 --- a/modules/implementation/src/llm/prompt.rs +++ b/modules/implementation/src/llm/prompt.rs @@ -36,6 +36,10 @@ impl Internal { request } } + + pub fn response_body_limit(&self) -> usize { + 4 * 4 * self.max_tokens as usize + 16 * 1024 * 1024 + } } #[derive(Serialize, Deserialize, Clone, Copy)] diff --git a/modules/implementation/src/llm/providers.rs b/modules/implementation/src/llm/providers.rs index 4966ae67e..ef560bb3d 100644 --- a/modules/implementation/src/llm/providers.rs +++ b/modules/implementation/src/llm/providers.rs @@ -337,7 +337,7 @@ impl Provider for OpenAICompatible { &url, prompt.apply_timeout(request), true, - usize::MAX, + prompt.response_body_limit(), ) .await?; @@ -418,7 +418,7 @@ impl Provider for OpenAICompatible { &url, prompt.apply_timeout(request), true, - usize::MAX, + prompt.response_body_limit(), ) .await?; @@ -525,7 +525,7 @@ impl Provider for OLlama { &url, prompt.apply_timeout(request), true, - usize::MAX, + prompt.response_body_limit(), ) .await?; @@ -584,7 +584,7 @@ impl Provider for OLlama { &url, prompt.apply_timeout(request), true, - usize::MAX, + prompt.response_body_limit(), ) .await?; @@ -667,7 +667,7 @@ impl Provider for Gemini { &url, prompt.apply_timeout(request), true, - usize::MAX, + prompt.response_body_limit(), ) .await?; @@ -729,7 +729,7 @@ impl Provider for Gemini { &url, prompt.apply_timeout(request), true, - usize::MAX, + prompt.response_body_limit(), ) .await?; @@ -851,7 +851,7 @@ impl Provider for Anthropic { &url, prompt.apply_timeout(request), true, - usize::MAX, + prompt.response_body_limit(), ) .await?; @@ -924,7 +924,7 @@ impl Provider for Anthropic { &url, prompt.apply_timeout(request), true, - usize::MAX, + prompt.response_body_limit(), ) .await?; @@ -994,7 +994,7 @@ impl Provider for Anthropic { &url, prompt.apply_timeout(request), true, - usize::MAX, + prompt.response_body_limit(), ) .await?; From bee96587c786407cdd112d16b2fd1d60b70d6612 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 02:17:07 +0900 Subject: [PATCH 053/124] =?UTF-8?q?chore(install):=20simplify=20post-insta?= =?UTF-8?q?ll=20to=20interpreter-only=20patching=20=E2=99=BB=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/python/post-install/__main__.py | 159 +++--------------- .../lib/python/post-install/requirements.txt | 3 +- 2 files changed, 29 insertions(+), 133 deletions(-) diff --git a/modules/install/lib/python/post-install/__main__.py b/modules/install/lib/python/post-install/__main__.py index 71d45a30d..0524d41ef 100644 --- a/modules/install/lib/python/post-install/__main__.py +++ b/modules/install/lib/python/post-install/__main__.py @@ -52,12 +52,6 @@ def str_to_bool_or_none(value): default=target_arch, help='Target architecture (amd64/arm64)', ) -parser.add_argument( - '--interactive', - type=str_to_bool, - default=False, - help='Whether to run in interactive mode', -) parser.add_argument( '--error-on-missing-executor', type=str_to_bool, @@ -146,8 +140,6 @@ def str_to_bool_or_none(value): if args.precompile is None: args.precompile = args.default_steps -INTERACTIVE = args.interactive - log_level_str = args.log_level log_levels = { 'DEBUG': logging.DEBUG, @@ -167,7 +159,13 @@ def str_to_bool_or_none(value): logging.info('Starting actual post-install script') -if args.bin_patch: +# Interpreter patching rewrites the ELF interpreter (dynamic loader) to the +# bundled one, whose path is only known at install time. It applies to ELF +# binaries (Linux) only; on other targets the loader is fixed and rpath/needed +# entries are already set correctly at build time, so lief is not needed. +patch_interpreter = args.bin_patch and args.os == 'linux' + +if patch_interpreter: import lief lief.logging.set_level(lief.logging.LEVEL.ERROR) @@ -220,8 +218,8 @@ def get_interpreter_path(): return interpreter_path -def patch_executable(path: Path, *, rpath_dir: list[Path]): - logger.info(f'Patching executable for {path}') +def patch_executable(path: Path): + logger.info(f'Patching interpreter for {path}') if not path.exists(): logger.warning(f'Path {path} does not exist, skipping patching') return @@ -231,125 +229,25 @@ def patch_executable(path: Path, *, rpath_dir: list[Path]): logger.error(f'Failed to parse binary at {path}') return - # Log basic binary information - logger.info(f'Binary format: {binary.format}') - - # Handle ELF binaries - if binary.format == lief.Binary.FORMATS.ELF: - logger.info(f'Processing ELF binary: {path}') - - # Log current interpreter - logger.info(f'Current interpreter: {binary.interpreter}') - - # Log current needed libraries - needed_libs = [ - lib if isinstance(lib, str) else lib.name for lib in binary.libraries - ] - logger.info(f'Current needed libraries: {needed_libs}') - - # Log current RPATH/RUNPATH - rpath_entries = [] - if binary.has(lief.ELF.DynamicEntry.TAG.RPATH): - rpath_entry = binary.get(lief.ELF.DynamicEntry.TAG.RPATH) - rpath_entries.append(f'RPATH: {rpath_entry.value}') - if binary.has(lief.ELF.DynamicEntry.TAG.RUNPATH): - runpath_entry = binary.get(lief.ELF.DynamicEntry.TAG.RUNPATH) - rpath_entries.append(f'RUNPATH: {runpath_entry.value}') - logger.info( - f'Current RPATH/RUNPATH entries: {rpath_entries if rpath_entries else "None"}' - ) + # rpath/needed entries are set correctly at build time, so the only install + # time fixup left is the ELF interpreter (dynamic loader) path. + if binary.format != lief.Binary.FORMATS.ELF: + logger.info(f'{path} is not ELF ({binary.format}), nothing to patch') + return - # Patch interpreter only for ELF - if Path(binary.interpreter).exists(): - logger.info( - f'Interpreter {binary.interpreter} exists, skipping interpreter patching' - ) - else: - old_interpreter = binary.interpreter - new_interpreter = str(get_interpreter_path()) - binary.interpreter = new_interpreter - logger.info(f'Updated interpreter from {old_interpreter} to: {new_interpreter}') - - # Update RPATH for ELF - logger.info(f'Updating RPATH for ELF binary') - - # Add or update RPATH entry - if binary.has(lief.ELF.DynamicEntry.TAG.RPATH): - # Update existing RPATH - rpath_entry = binary.get(lief.ELF.DynamicEntry.TAG.RPATH) - old_rpath = str(rpath_entry.value) - rpath_entry.paths = [str(rpath) for rpath in rpath_dir] - logger.info(f'Updated RPATH from "{old_rpath}" to: "{rpath_entry.value}"') - else: - # Add new RPATH entry - rpath_entry = lief.ELF.DynamicEntryRpath([str(rpath) for rpath in rpath_dir]) - binary.add(rpath_entry) - logger.info(f'Added new RPATH entry: "{rpath_dir}"') - - # Handle Mach-O binaries - elif binary.format == lief.Binary.FORMATS.MACHO: - logger.info(f'Processing Mach-O binary: {path}') - - # Log current RPATH commands - existing_rpaths = [] - for cmd in binary.commands: - if cmd.command == lief.MachO.LoadCommand.TYPE.RPATH: - existing_rpaths.append(cmd.path) + logger.info(f'Current interpreter: {binary.interpreter}') + if Path(binary.interpreter).exists(): logger.info( - f'Current RPATH entries: {existing_rpaths if existing_rpaths else "None"}' + f'Interpreter {binary.interpreter} exists, skipping interpreter patching' ) - - # Log current needed libraries - needed_libs = [] - for cmd in binary.commands: - if cmd.command in [ - lief.MachO.LoadCommand.TYPE.LOAD_DYLIB, - lief.MachO.LoadCommand.TYPE.LOAD_WEAK_DYLIB, - ]: - needed_libs.append(cmd.name) - logger.info(f'Current needed libraries: {needed_libs}') - - # Replace specific library references - for cmd in binary.commands: - if cmd.command in [ - lief.MachO.LoadCommand.TYPE.LOAD_DYLIB, - lief.MachO.LoadCommand.TYPE.LOAD_WEAK_DYLIB, - ]: - if cmd.name == '/usr/local/lib/libiconv.2.dylib': - old_name = cmd.name - cmd.name = '@rpath/libiconv.dylib' - logger.info(f'Replaced library reference: "{old_name}" -> "{cmd.name}"') - elif '/' not in cmd.name: - old_name = cmd.name - cmd.name = '@rpath/' + cmd.name - logger.info(f'Replaced library reference: "{old_name}" -> "{cmd.name}"') - - # Set RPATH for Mach-O - - for rpath in rpath_dir: - rpath_str = str(rpath) - rpath_cmd = lief.MachO.RPathCommand.create(rpath_str) - binary.add(rpath_cmd) - logger.info(f'Added RPATH to Mach-O binary: "{rpath_str}"') - - else: - logger.warning(f'Unsupported binary format for {path}: {binary.format}') return - # Write the modified binary - binary.write(str(path)) - logger.info(f'Successfully patched binary: {path}') + old_interpreter = binary.interpreter + binary.interpreter = str(get_interpreter_path()) + logger.info(f'Updated interpreter from {old_interpreter} to: {binary.interpreter}') - if binary.format == lief.Binary.FORMATS.MACHO: - logger.info(f'Trying to code sign Mach-O binary: {path}') - try: - subprocess.run(['codesign', '--force', '--sign', '-', path], check=True) - except Exception as e: - logger.error( - f'Failed to code sign Mach-O binary {path}: {e}. This may be critical. You can rerun with INTERACTIVE=true environment variable to pause on this error.' - ) - if INTERACTIVE: - input('Waiting for user to fix the issue. Press Enter to continue...') + binary.write(str(path)) + logger.info(f'Successfully patched interpreter: {path}') def run_check_command(command: list[str | Path]): @@ -363,8 +261,8 @@ def run_check_command(command: list[str | Path]): modules_executable = genvm_root_dir.joinpath('bin', 'genvm-modules') -if args.bin_patch: - patch_executable(modules_executable, rpath_dir=[genvm_root_dir.joinpath('lib')]) +if patch_interpreter: + patch_executable(modules_executable) if args.bin_check: run_check_command([modules_executable, '--version']) @@ -505,7 +403,7 @@ def process_executor_version(executor_version: str): executor_root_dir = genvm_root_dir.joinpath('executor', executor_version) executor_executable = executor_root_dir.joinpath('bin', 'genvm') - if args.executor_download or args.bin_patch or args.bin_check: + if args.executor_download or patch_interpreter or args.bin_check: if not executor_executable.exists() and args.executor_download: import lzma @@ -549,11 +447,8 @@ def process_executor_version(executor_version: str): else: logger.warning(f'Executor path {executor_executable} does not exist, skipping') return - if args.bin_patch: - patch_executable( - executor_executable, - rpath_dir=[genvm_root_dir.joinpath('lib'), executor_root_dir.joinpath('lib')], - ) + if patch_interpreter: + patch_executable(executor_executable) if args.bin_check: run_check_command([executor_executable, '--version']) diff --git a/modules/install/lib/python/post-install/requirements.txt b/modules/install/lib/python/post-install/requirements.txt index c259fe8c5..4c36ff855 100644 --- a/modules/install/lib/python/post-install/requirements.txt +++ b/modules/install/lib/python/post-install/requirements.txt @@ -1,2 +1,3 @@ -lief==0.17.0 +# only needed for ELF interpreter patching (see post-install __main__.py) +lief==0.17.0; platform_system == "Linux" pyyaml==6.0.3 From 15698af8553e41b2b37381d94d0b9bb4b8924e7c Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 02:21:36 +0900 Subject: [PATCH 054/124] =?UTF-8?q?chore(abi):=20always=20encode=20user=20?= =?UTF-8?q?errors=20as=20tagged=20calldata=20=E2=99=BB=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../crates/sdk-rs/examples/fetch_webpage.rs | 6 +++- executor/crates/sdk-rs/src/abi/entry.rs | 15 ++++++---- executor/src/rt/vm/mod.rs | 13 +++------ executor/src/wasi/genlayer_sdk.rs | 28 ++++++++----------- 4 files changed, 30 insertions(+), 32 deletions(-) diff --git a/executor/crates/sdk-rs/examples/fetch_webpage.rs b/executor/crates/sdk-rs/examples/fetch_webpage.rs index 59bf9a4ac..8ef1e27c0 100644 --- a/executor/crates/sdk-rs/examples/fetch_webpage.rs +++ b/executor/crates/sdk-rs/examples/fetch_webpage.rs @@ -167,7 +167,11 @@ fn run_nondet(entry_data: &[u8]) -> Result { match result { LeaderResult::Return(value) => Ok(value), - LeaderResult::UserError(msg) => { + LeaderResult::UserError(value) => { + let msg = match value { + Value::Str(s) => s, + other => format!("{other:?}"), + }; genlayer_sdk::abi::entry::user_error_immediately(msg); } LeaderResult::VmError(msg) => { diff --git a/executor/crates/sdk-rs/src/abi/entry.rs b/executor/crates/sdk-rs/src/abi/entry.rs index fd22e65f0..b77315967 100644 --- a/executor/crates/sdk-rs/src/abi/entry.rs +++ b/executor/crates/sdk-rs/src/abi/entry.rs @@ -406,7 +406,7 @@ pub mod contract_def { #[derive(Debug, Clone)] pub enum LeaderResult { Return(Value), - UserError(String), + UserError(Value), VmError(String), } @@ -428,11 +428,14 @@ pub mod contract_def { Ok(LeaderResult::Return(value)) } ResultCode::UserError => { - // FIXME: deprecate in next release (raw-string user error encoding; - // switch to the tagged calldata form) - let msg = String::from_utf8(rest.to_vec()) - .map_err(|e| ConsensusStageParseError::InvalidUtf8(e.to_string()))?; - Ok(LeaderResult::UserError(msg)) + if rest.len() < 4 || rest[..4] != [0u8; 4] { + return Err(ConsensusStageParseError::DecodeError( + "missing tagged calldata prefix in user error".to_owned(), + )); + } + let value = calldata::decode(&rest[4..]) + .map_err(|e| ConsensusStageParseError::DecodeError(e.to_string()))?; + Ok(LeaderResult::UserError(value)) } ResultCode::VmError | ResultCode::InternalError => { let msg = String::from_utf8(rest.to_vec()) diff --git a/executor/src/rt/vm/mod.rs b/executor/src/rt/vm/mod.rs index 5071c71b3..51a0a3b02 100644 --- a/executor/src/rt/vm/mod.rs +++ b/executor/src/rt/vm/mod.rs @@ -91,18 +91,13 @@ impl RunOk { } RunOk::UserError(val) => { let mut res = vec![ResultCode::UserError as u8]; + res.extend_from_slice(&0u32.to_le_bytes()); match val { - // FIXME: deprecate in next release (always use the tagged calldata form below) - calldata::unparsed::Maybe::Materialized(calldata::Value::Str(s)) => { - res.extend_from_slice(s.as_bytes()); + calldata::unparsed::Maybe::Materialized(value) => { + res.extend_from_slice(&calldata::encode(value)); } - calldata::unparsed::Maybe::Materialized(other) => { - res.extend_from_slice(&0u32.to_le_bytes()); - res.extend_from_slice(&calldata::encode(other)); - } - // Already-encoded calldata bytes; emit them in the tagged form. + // Already-encoded calldata bytes. calldata::unparsed::Maybe::Checked(raw) => { - res.extend_from_slice(&0u32.to_le_bytes()); res.extend_from_slice(&raw.0); } } diff --git a/executor/src/wasi/genlayer_sdk.rs b/executor/src/wasi/genlayer_sdk.rs index 401dff27c..70db506c4 100644 --- a/executor/src/wasi/genlayer_sdk.rs +++ b/executor/src/wasi/genlayer_sdk.rs @@ -1693,22 +1693,18 @@ impl ContextVFS<'_> { )) } x if x == ResultCode::UserError as u8 => { - let val = if rest.len() >= 4 && rest[..4] == [0u8; 4] { - calldata::decode(&rest[4..]).map_err(|e| { - generated::types::Error::trap(crate::anyhow_to_wasmtime( - anyhow::anyhow!(e), - )) - })? - } else { - // FIXME: deprecate in next release (raw-string user error encoding) - calldata::Value::Str(String::from(std::str::from_utf8(rest).map_err( - |e| { - generated::types::Error::trap(crate::anyhow_to_wasmtime( - anyhow::anyhow!(e), - )) - }, - )?)) - }; + if rest.len() < 4 || rest[..4] != [0u8; 4] { + return Err(generated::types::Error::trap(crate::anyhow_to_wasmtime( + anyhow::anyhow!( + "invalid user error encoding: missing tagged calldata prefix" + ), + ))); + } + let val = calldata::decode(&rest[4..]).map_err(|e| { + generated::types::Error::trap(crate::anyhow_to_wasmtime( + anyhow::anyhow!(e), + )) + })?; rt::vm::RunOk::UserError(calldata::unparsed::Maybe::Materialized(val)) } x if x == ResultCode::VmError as u8 => { From e8913cf08492f17f48931b239eb92664d1b64524 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 02:25:07 +0900 Subject: [PATCH 055/124] =?UTF-8?q?chore(abi):=20make=20json=20llm=20outpu?= =?UTF-8?q?t=20format=20behave=20like=20json2=20=E2=99=BB=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/crates/sdk-rs/src/abi/gl_call.rs | 3 ++- executor/src/wasi/genlayer_sdk.rs | 29 ++--------------------- 2 files changed, 4 insertions(+), 28 deletions(-) diff --git a/executor/crates/sdk-rs/src/abi/gl_call.rs b/executor/crates/sdk-rs/src/abi/gl_call.rs index 99f121360..1e0a36b94 100644 --- a/executor/crates/sdk-rs/src/abi/gl_call.rs +++ b/executor/crates/sdk-rs/src/abi/gl_call.rs @@ -231,7 +231,8 @@ pub mod llm_iface { #[serde(rename = "text")] #[calldata(rename = "text")] Text, - // FIXME: deprecate in next release (json will adopt json2 behavior) + // `json` and `json2` are accepted aliases with identical behavior: the raw + // model text is returned as-is and the contract parses it. #[serde(rename = "json")] #[calldata(rename = "json")] JSON, diff --git a/executor/src/wasi/genlayer_sdk.rs b/executor/src/wasi/genlayer_sdk.rs index 70db506c4..f7e0be7e8 100644 --- a/executor/src/wasi/genlayer_sdk.rs +++ b/executor/src/wasi/genlayer_sdk.rs @@ -1,7 +1,6 @@ use std::collections::BTreeMap; use std::sync::Arc; -use genlayer_sdk::abi::gl_call::llm_iface; use genvm_common::sync::DArc; use genvm_common::*; @@ -10,7 +9,6 @@ use sha3::digest::Update; use wiggle::GuestError; use crate::host::{self, SlotID}; -use crate::wasi::json_to_calldata::json_map_to_calldata; use crate::{anyhow_to_wasmtime, calldata, public_abi, rt, wasi}; use genlayer_calldata::codec::Encode; @@ -1159,7 +1157,6 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { let sup = self.context.data.supervisor.clone(); let task = taskify(async move { - let format = prompt_payload.response_format; let result = sup .modules .llm @@ -1185,7 +1182,7 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { if result.consumed_gen == primitive_types::U256::MAX { return Err( - rt::errors::VMError(abi::consts::VmError::timeout(), None).into(), + rt::errors::VMError(abi::consts::VmError::timeout(), None).into() ); } @@ -1194,29 +1191,7 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { *acc = acc.saturating_add(result.consumed_gen); } - let mut result = result.data; - - if format == llm_iface::OutputFormat::JSON { - let genvm_modules_interfaces::llm::PromptAnswerData::Text(t) = result - else { - return Err(anyhow::anyhow!("expected text response for json format")); - }; - - let val: serde_json::Map = - serde_json::from_str(&t).map_err(|e| { - generated::types::Error::trap(crate::anyhow_to_wasmtime(e.into())) - })?; - - log_debug!(text = t; "for backwards compatibility we convert text to object for JSON 1"); - - std::mem::drop(t); - - let val = json_map_to_calldata(val); - - log_debug!(converted:serde = val; "for backwards compatibility we convert text to object for JSON 1"); - - result = genvm_modules_interfaces::llm::PromptAnswerData::Object(val); - } + let result = result.data; Ok(Ok(result)) }) From 05c15904da2b2bbeacb2ffe1ca3ef13b141e1dad Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 02:26:41 +0900 Subject: [PATCH 056/124] =?UTF-8?q?chore(abi):=20remove=20deprecated=20Rol?= =?UTF-8?q?lback=20gl=5Fcall=20message=20variant=20=F0=9F=94=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/crates/sdk-rs/src/abi/gl_call.rs | 3 --- executor/src/wasi/genlayer_sdk.rs | 4 ---- 2 files changed, 7 deletions(-) diff --git a/executor/crates/sdk-rs/src/abi/gl_call.rs b/executor/crates/sdk-rs/src/abi/gl_call.rs index 1e0a36b94..41b7d8938 100644 --- a/executor/crates/sdk-rs/src/abi/gl_call.rs +++ b/executor/crates/sdk-rs/src/abi/gl_call.rs @@ -595,9 +595,6 @@ pub enum Message { ExecPrompt(llm_iface::PromptPayload), ExecPromptTemplate(llm_iface::PromptTemplatePayload), - // FIXME: deprecate in next release - #[deprecated(note = "Use UserError. Will be removed before 1.0 release")] - Rollback(calldata::unparsed::Maybe), UserError(calldata::unparsed::Maybe), Return(calldata::unparsed::Maybe), diff --git a/executor/src/wasi/genlayer_sdk.rs b/executor/src/wasi/genlayer_sdk.rs index f7e0be7e8..65d01f508 100644 --- a/executor/src/wasi/genlayer_sdk.rs +++ b/executor/src/wasi/genlayer_sdk.rs @@ -1276,10 +1276,6 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { self.place_content(vfs::FileContents::from(bytes::Bytes::from(task))) } - #[allow(deprecated)] - gl_call::Message::Rollback(msg) => Err(generated::types::Error::trap( - crate::anyhow_to_wasmtime(rt::errors::UserError(msg).into()), - )), gl_call::Message::UserError(msg) => Err(generated::types::Error::trap( crate::anyhow_to_wasmtime(rt::errors::UserError(msg).into()), )), From 9f361b155482d5882af10474b560b5e04320319b Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 14:08:27 +0900 Subject: [PATCH 057/124] =?UTF-8?q?fix(executor):=20reject=20'..'=20compon?= =?UTF-8?q?ents=20when=20mapping=20archive=20files=20=F0=9F=94=92=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/src/rt/supervisor/actions.rs | 30 ++++++++++++++++++--------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/executor/src/rt/supervisor/actions.rs b/executor/src/rt/supervisor/actions.rs index 60841c04d..454df3dab 100644 --- a/executor/src/rt/supervisor/actions.rs +++ b/executor/src/rt/supervisor/actions.rs @@ -30,6 +30,24 @@ fn maps_into_vm(to: &str) -> bool { to.split('/').find(|component| !component.is_empty()) == Some("vm") } +/// Rejects mapping targets that are forbidden or could escape their intended +/// location. `maps_into_vm` only inspects the first component, so a `..` +/// component (e.g. from an archive entry name like `../vm/secrets`) would slip +/// past it and resolve into `/vm/` once the VFS normalizes the path. +fn check_mapping_target(to: &str) -> anyhow::Result<()> { + if maps_into_vm(to) { + return Err(make_malformed_runner_error(&format!( + "mapping into /vm/ is forbidden: {to}" + ))); + } + if to.split('/').any(|component| component == "..") { + return Err(make_malformed_runner_error(&format!( + "mapping path with a '..' component is forbidden: {to}" + ))); + } + Ok(()) +} + /// How a resolved runner id should be loaded into the archive cache. enum ResolvedKind { /// A packaged `name:hash` runner read from the runners directory. @@ -272,11 +290,7 @@ pub(crate) fn map_archive_file( } name_in_fs.push_str(&name[must_start_with.len()..]); - if maps_into_vm(&name_in_fs) { - return Err(make_malformed_runner_error(&format!( - "mapping into /vm/ is forbidden: {name_in_fs}" - ))); - } + check_mapping_target(&name_in_fs)?; if !limiter .consume(public_abi::memory_limiter_consts::FILE_MAPPING + name_in_fs.len() as u32) @@ -289,11 +303,7 @@ pub(crate) fn map_archive_file( preview1.map_file(&name_in_fs, file_contents.clone())?; } } else { - if maps_into_vm(to) { - return Err(make_malformed_runner_error(&format!( - "mapping into /vm/ is forbidden: {to}" - ))); - } + check_mapping_target(to)?; if !limiter.consume(public_abi::memory_limiter_consts::FILE_MAPPING + to.len() as u32) { return Err(rt::errors::VMError(abi::consts::VmError::oom().ram().val(), None).into()); From 52e201b9cdf14f56fb3096711d23e2c037a4bd2c Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 14:08:45 +0900 Subject: [PATCH 058/124] =?UTF-8?q?fix(executor):=20require=200x=20prefix?= =?UTF-8?q?=20on=20chain=20runner=20addresses=20=F0=9F=94=92=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/src/runners/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/executor/src/runners/mod.rs b/executor/src/runners/mod.rs index 73d7c9a07..a2f3a1ae5 100644 --- a/executor/src/runners/mod.rs +++ b/executor/src/runners/mod.rs @@ -126,7 +126,7 @@ fn is_hash_char(c: char) -> bool { } fn parse_hex_fixed(s: &str) -> Option<[u8; N]> { - let s = s.strip_prefix("0x").unwrap_or(s); + let s = s.strip_prefix("0x")?; if s.len() != N * 2 { return None; } @@ -354,6 +354,7 @@ mod tests { // chain: closed grammar assert!(parse_runner_id(&format!("chain:0x01:f:{}", slot64())).is_none()); // short address + assert!(parse_runner_id(&format!("chain:{}:f:{}", "0".repeat(40), slot64())).is_none()); // missing 0x assert!(parse_runner_id(&format!("chain:{}:f:0x02", addr40())).is_none()); // short slot assert!(parse_runner_id(&format!("chain:{}:x:{}", addr40(), slot64())).is_none()); // bad a|f assert!(parse_runner_id(&format!("chain:{}:f:{}:extra", addr40(), slot64())).is_none()); // extra segment From e07012c7dd952032291f38d324444fa464bcd2b2 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 14:08:54 +0900 Subject: [PATCH 059/124] =?UTF-8?q?fix(common):=20fail-fast=20on=20malform?= =?UTF-8?q?ed=20version=20strings=20=F0=9F=90=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/crates/common/src/version.rs | 31 +++++++++++++++++++++------ 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/executor/crates/common/src/version.rs b/executor/crates/common/src/version.rs index 5b17e231a..d3c2b02b1 100644 --- a/executor/crates/common/src/version.rs +++ b/executor/crates/common/src/version.rs @@ -73,13 +73,15 @@ impl Version { /// Parses a `u16` starting at `i`, returning the value and the index past the /// last digit consumed. -const fn parse_u16(s: &[u8], mut i: usize) -> (u16, usize) { +const fn parse_u16(s: &[u8], mut i: usize) -> (u16, usize, bool) { let mut n: u16 = 0; + let mut consumed = false; while i < s.len() && s[i] >= b'0' && s[i] <= b'9' { n = n * 10 + (s[i] - b'0') as u16; i += 1; + consumed = true; } - (n, i) + (n, i, consumed) } const fn const_starts_with(s: &[u8], prefix: &[u8]) -> bool { @@ -102,8 +104,14 @@ const fn current_version() -> Version { // version (kept at the active dev major/minor via `.genvm-monorepo-root`) // with a max patch so it sorts newer than any real release of that line. let pkg = env!("CARGO_PKG_VERSION").as_bytes(); - let (major, i) = parse_u16(pkg, 0); - let (minor, _) = parse_u16(pkg, i + 1); // skip the '.' + let (major, i, ok_major) = parse_u16(pkg, 0); + if !ok_major || i >= pkg.len() || pkg[i] != b'.' { + panic!("invalid CARGO_PKG_VERSION: missing major"); + } + let (minor, _, ok_minor) = parse_u16(pkg, i + 1); // skip the '.' + if !ok_minor { + panic!("invalid CARGO_PKG_VERSION: missing minor"); + } return Version { major, minor, @@ -118,9 +126,18 @@ const fn current_version() -> Version { } else { 0 }; - let (major, i) = parse_u16(id, start); - let (minor, i) = parse_u16(id, i + 1); // skip '.' - let (patch, _) = parse_u16(id, i + 1); // skip '.' + let (major, i, ok_major) = parse_u16(id, start); + if !ok_major || i >= id.len() || id[i] != b'.' { + panic!("invalid VERSION: missing major"); + } + let (minor, i, ok_minor) = parse_u16(id, i + 1); // skip '.' + if !ok_minor || i >= id.len() || id[i] != b'.' { + panic!("invalid VERSION: missing minor"); + } + let (patch, _, ok_patch) = parse_u16(id, i + 1); // skip '.' + if !ok_patch { + panic!("invalid VERSION: missing patch"); + } Version { major, minor, From 6e023f4398a7bc529aff83c04f97f31f6c10d2bd Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 14:08:55 +0900 Subject: [PATCH 060/124] =?UTF-8?q?docs(sdk):=20gvm32=20encode=20emits=20l?= =?UTF-8?q?owercase,=20not=20uppercase=20=F0=9F=93=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/crates/sdk-rs/src/gvm32.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/executor/crates/sdk-rs/src/gvm32.rs b/executor/crates/sdk-rs/src/gvm32.rs index 59bddd178..2231d69e2 100644 --- a/executor/crates/sdk-rs/src/gvm32.rs +++ b/executor/crates/sdk-rs/src/gvm32.rs @@ -8,7 +8,7 @@ const ALPHABET: &[u8] = b"0123456789abcdefghjkmnpqrstvwxyz"; -/// Encodes a byte slice as a Crockford Base32 string (uppercase, no padding). +/// Encodes a byte slice as a Crockford Base32 string (lowercase, no padding). pub fn encode(bytes: &[u8]) -> String { let mut out = String::with_capacity(bytes.len() * 8 / 5 + 1); let mut value: u32 = 0; From 1bde44cfcc6a1743d9a49096a506fb554199b792 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 14:08:56 +0900 Subject: [PATCH 061/124] =?UTF-8?q?fix(llm):=20hard-cap=20derived=20respon?= =?UTF-8?q?se=20body=20limit=20=F0=9F=94=92=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/implementation/src/llm/prompt.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/modules/implementation/src/llm/prompt.rs b/modules/implementation/src/llm/prompt.rs index 4ca10f281..c81ed3588 100644 --- a/modules/implementation/src/llm/prompt.rs +++ b/modules/implementation/src/llm/prompt.rs @@ -37,8 +37,18 @@ impl Internal { } } + /// Upper bound on the provider response body we buffer in memory. Budgets + /// ~16 bytes per requested output token (~4 bytes/char * ~4 chars/token) + /// plus a 16 MiB base, hard-capped so a large `max_tokens` cannot blow up + /// the limit (`u32::MAX` would otherwise allow ~64 GiB). pub fn response_body_limit(&self) -> usize { - 4 * 4 * self.max_tokens as usize + 16 * 1024 * 1024 + const BASE_LIMIT: usize = 16 * 1024 * 1024; + const MAX_LIMIT: usize = 32 * 1024 * 1024; + + (self.max_tokens as usize) + .saturating_mul(16) + .saturating_add(BASE_LIMIT) + .min(MAX_LIMIT) } } From 38c52fdf65d84ecb0a68965e472cdf284cebdebf Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 14:08:57 +0900 Subject: [PATCH 062/124] =?UTF-8?q?fix(install):=20fail=20closed=20on=20mi?= =?UTF-8?q?ssing=20executor=20integrity=20hash=20=F0=9F=94=92=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/install/lib/python/post-install/__main__.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/install/lib/python/post-install/__main__.py b/modules/install/lib/python/post-install/__main__.py index 0524d41ef..eb15030bd 100644 --- a/modules/install/lib/python/post-install/__main__.py +++ b/modules/install/lib/python/post-install/__main__.py @@ -430,10 +430,14 @@ def process_executor_version(executor_version: str): if expected_hash is not None: if not runner_check_bytes(tar_data, expected_hash): raise ValueError(f'hash mismatch for executor {executor_version}') - else: + elif executor_version == 'vTEST': logger.warning( f'no integrity hash for executor {executor_version}; skipping verification' ) + else: + raise ValueError( + f'no integrity hash for executor {executor_version}; refusing to extract' + ) # filter='data' rejects absolute / `..` paths and unsafe link and device # members, preventing writes outside genvm_root_dir (tar path-traversal / From 5a8c14e2f60c179d472b2df3f9d808ab7e575c31 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 14:17:51 +0900 Subject: [PATCH 063/124] =?UTF-8?q?docs(py-std):=20gvm32=20encode=20emits?= =?UTF-8?q?=20lowercase,=20not=20uppercase=20=F0=9F=93=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- runners/genlayer-py-std/src/genlayer/gvm32.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runners/genlayer-py-std/src/genlayer/gvm32.py b/runners/genlayer-py-std/src/genlayer/gvm32.py index e0e7f9709..c0f7f9fa8 100644 --- a/runners/genlayer-py-std/src/genlayer/gvm32.py +++ b/runners/genlayer-py-std/src/genlayer/gvm32.py @@ -18,7 +18,7 @@ def encode(data: collections.abc.Buffer) -> str: """ - Encode a byte buffer to its Crockford Base32 string (uppercase, no padding). + Encode a byte buffer to its Crockford Base32 string (lowercase, no padding). :param data: bytes to encode :returns: the base32-encoded string From b44a79ad2b7f4b6e739c81a5813ed57b4b9ee1b6 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 14:17:51 +0900 Subject: [PATCH 064/124] =?UTF-8?q?fix(nix):=20validate=20hex=20length=20a?= =?UTF-8?q?nd=20runner=20uid=20format=20=F0=9F=94=92=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- runners/support/gvm32.nix | 8 +++++++- runners/support/views/all-universal.nix | 6 +++++- runners/support/views/debug-build.nix | 6 +++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/runners/support/gvm32.nix b/runners/support/gvm32.nix index 804f8f35e..21e34eff4 100644 --- a/runners/support/gvm32.nix +++ b/runners/support/gvm32.nix @@ -22,7 +22,13 @@ let hexToBytes = hex: let chars = lib.stringToCharacters hex; - n = (builtins.length chars) / 2; + charsLen = builtins.length chars; + # integer division truncates, so reject odd lengths instead of + # silently dropping the final nibble (which would corrupt the hash). + n = + if charsLen / 2 * 2 != charsLen + then throw "gvm32.hexToBytes: hex string length must be even" + else charsLen / 2; in builtins.genList (i: hexValues.${builtins.elemAt chars (i * 2)} * 16 diff --git a/runners/support/views/all-universal.nix b/runners/support/views/all-universal.nix index c221a0376..d46309fcf 100644 --- a/runners/support/views/all-universal.nix +++ b/runners/support/views/all-universal.nix @@ -11,7 +11,11 @@ dontBuild = true; dontFixup = true; installPhase = let - hash32 = builtins.head (builtins.tail (builtins.match "([^:]+):(.*)" x.uid)); + uidMatch = builtins.match "([^:]+):(.+)" x.uid; + hash32 = + if uidMatch == null + then throw "invalid runner uid `${x.uid}`; expected `:`" + else builtins.elemAt uidMatch 1; result-path = "runners/${x.id}/${builtins.substring 0 2 hash32}/${builtins.substring 2 50 hash32}.tar"; in '' mkdir -p $out/$(dirname -- ${result-path}) diff --git a/runners/support/views/debug-build.nix b/runners/support/views/debug-build.nix index 3d206db7b..d5fe31f88 100644 --- a/runners/support/views/debug-build.nix +++ b/runners/support/views/debug-build.nix @@ -9,7 +9,11 @@ let pathOfRunner = runner: let # the gvm32 hash id (matches `uid` / `hashToIDHash`) - hash32 = builtins.head (builtins.tail (builtins.match "([^:]+):(.*)" runner.uid)); + uidMatch = builtins.match "([^:]+):(.+)" runner.uid; + hash32 = + if uidMatch == null + then throw "invalid runner uid `${runner.uid}`; expected `:`" + else builtins.elemAt uidMatch 1; in "${runner.id}/${builtins.substring 0 2 hash32}/${builtins.substring 2 50 hash32}.tar"; installLines = From db54fd5f4c3ba7b2b46e64d8606349a74368b64f Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 14:42:27 +0900 Subject: [PATCH 065/124] =?UTF-8?q?feat(executor):=20CallContract=20child?= =?UTF-8?q?=20is=20static=20=E2=80=94=20forbid=20events=20and=20message=20?= =?UTF-8?q?sends=20=F0=9F=94=92=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/website/src/spec/03-vm/05-permissions.rst | 13 ++++++--- executor/src/wasi/genlayer_sdk.rs | 15 ++++++++++- .../py/intercontract/call_view_emit.0.hash | 1 + .../py/intercontract/call_view_emit.0.stdout | 1 + .../py/intercontract/call_view_emit.0_0.hash | 1 + .../intercontract/call_view_emit.0_0.stdout | 1 + .../intercontract/call_view_emit.0_0_0.hash | 1 + .../intercontract/call_view_emit.0_0_0.stdout | 4 +++ .../py/intercontract/call_view_emit.jsonnet | 10 +++++++ .../py/intercontract/call_view_emit_from.py | 17 ++++++++++++ .../py/intercontract/call_view_emit_to.py | 27 +++++++++++++++++++ 11 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 tests/cases/stable/py/intercontract/call_view_emit.0.hash create mode 100644 tests/cases/stable/py/intercontract/call_view_emit.0.stdout create mode 100644 tests/cases/stable/py/intercontract/call_view_emit.0_0.hash create mode 100644 tests/cases/stable/py/intercontract/call_view_emit.0_0.stdout create mode 100644 tests/cases/stable/py/intercontract/call_view_emit.0_0_0.hash create mode 100644 tests/cases/stable/py/intercontract/call_view_emit.0_0_0.stdout create mode 100644 tests/cases/stable/py/intercontract/call_view_emit.jsonnet create mode 100644 tests/cases/stable/py/intercontract/call_view_emit_from.py create mode 100644 tests/cases/stable/py/intercontract/call_view_emit_to.py diff --git a/doc/website/src/spec/03-vm/05-permissions.rst b/doc/website/src/spec/03-vm/05-permissions.rst index 111b74846..f0438b681 100644 --- a/doc/website/src/spec/03-vm/05-permissions.rst +++ b/doc/website/src/spec/03-vm/05-permissions.rst @@ -28,6 +28,8 @@ Allows reading contract storage slots. When unset, any attempt to read storage w Allows writing to contract storage slots. Requires :ref:`gvm-perm-deterministic` as well. +This permission also gates ``EmitEvent``: a VM may emit events *iff* it can write storage, since events are state-mutating log emissions. Consequently a read-only (static) context, such as a ``CallContract`` child, cannot emit events. + .. _gvm-perm-send-messages: ``send_messages`` @@ -67,9 +69,12 @@ Different operations modify permissions when creating child :term:`sub-VM` insta ``CallContract`` ~~~~~~~~~~~~~~~~ -Inherits all parent permissions except: +A ``CallContract`` child runs as a read-only (static) call. It inherits all parent permissions except: - :ref:`gvm-perm-write-storage` is **disabled** +- :ref:`gvm-perm-send-messages` is **disabled** + +A static call must not produce externally visible effects, so storage writes, message sends, and event emissions all fail: emitting an event additionally requires :ref:`gvm-perm-write-storage` (disabled here). Allowing any such emission would charge fees for effects that are discarded together with the child VM. ``RunNondet`` ~~~~~~~~~~~~~ @@ -90,8 +95,8 @@ The sandboxed :term:`sub-VM` has: - :ref:`gvm-perm-deterministic` is **inherited** - :ref:`gvm-perm-read-storage` is **inherited** -- :ref:`gvm-perm-write-storage` is **inherited** if ``allow_write_storage`` is set, otherwise **disabled** +- :ref:`gvm-perm-write-storage` is **inherited** *iff* ``allow_write_storage`` is set, otherwise **disabled** - :ref:`gvm-perm-spawn-nondet` is **disabled** - :ref:`gvm-perm-call-others` is **disabled** -- :ref:`gvm-perm-send-messages` is **inherited** if ``allow_send_messages`` is set, otherwise **disabled** -- :ref:`gvm-perm-register-runners` is **inherited** if ``allow_register_runners`` is set, otherwise **disabled** +- :ref:`gvm-perm-send-messages` is **inherited** *iff* ``allow_send_messages`` is set, otherwise **disabled** +- :ref:`gvm-perm-register-runners` is **inherited** *iff* ``allow_register_runners`` is set, otherwise **disabled** diff --git a/executor/src/wasi/genlayer_sdk.rs b/executor/src/wasi/genlayer_sdk.rs index 65d01f508..d0b815f07 100644 --- a/executor/src/wasi/genlayer_sdk.rs +++ b/executor/src/wasi/genlayer_sdk.rs @@ -716,7 +716,11 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { can_write_storage: false, can_spawn_nondet: my_conf.can_spawn_nondet, can_call_others: my_conf.can_call_others, - can_send_messages: my_conf.can_send_messages, + // A `CallContract` child is read-only (static): it cannot + // write storage, send messages, or emit events. Emissions + // from the child are discarded, so allowing them would + // charge fees for effects that never surface. + can_send_messages: false, can_register_runners: my_conf.can_register_runners, state_mode: state, code_slot: crate::SlotID::ZERO, @@ -776,6 +780,15 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { return Err(generated::types::Errno::Forbidden.into()); } + // Events are state-mutating log emissions, so they require the + // same write capability as storage. A read-only sub-VM (e.g. a + // `CallContract` child) must not emit events; otherwise the + // emission is charged but later discarded with the child. + if !self.context.data.conf.can_write_storage { + log_warn!("EmitEvent requires write_storage permission"); + + return Err(generated::types::Errno::Forbidden.into()); + } if topics.len() > public_abi::EVENT_MAX_TOPICS as usize { log_warn!(cnt = topics.len(), max = public_abi::EVENT_MAX_TOPICS; "too many topics"); diff --git a/tests/cases/stable/py/intercontract/call_view_emit.0.hash b/tests/cases/stable/py/intercontract/call_view_emit.0.hash new file mode 100644 index 000000000..7d38b1914 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_view_emit.0.hash @@ -0,0 +1 @@ +LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDLK0CAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIFBpbmdlZChnbC5jaGFpbi5FdmVudCk6CglkZWYgX19pbml0X18oc2VsZiwgd2hvOiBzdHIsIC8sICoqYmxvYik6IC4uLgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwYXNzCgoJQGdsLnB1YmxpYy52aWV3CglkZWYgcGluZyhzZWxmKSAtPiBzdHI6CgkJIyBpbnNpZGUgYSBDYWxsQ29udHJhY3QgY2hpbGQgVk0gKHJlYWQtb25seSAvIHN0YXRpYyBjYWxsKQoJCXRyeToKCQkJUGluZ2VkKCdiJywgbm90ZT0nZW1pdHRlZCBkdXJpbmcgQ2FsbENvbnRyYWN0JykuZW1pdCgpCgkJCXByaW50KCdCIGVtaXQ6IG9rJykKCQlleGNlcHQgRXhjZXB0aW9uIGFzIGU6CgkJCXByaW50KGYnQiBlbWl0IGZvcmJpZGRlbjoge3R5cGUoZSkuX19uYW1lX199JykKCQl0cnk6CgkJCWdsLmNvbnRyYWN0LmdldF9hdChnbC5BZGRyZXNzKGInXHgzMCcgKiAyMCkpLmVtaXQoKS5mb28oMSwgMikKCQkJcHJpbnQoJ0Igc2VuZDogb2snKQoJCWV4Y2VwdCBFeGNlcHRpb24gYXMgZToKCQkJcHJpbnQoZidCIHNlbmQgZm9yYmlkZGVuOiB7dHlwZShlKS5fX25hbWVfX30nKQoJCXJldHVybiAncG9uZycKAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/intercontract/call_view_emit.0.stdout b/tests/cases/stable/py/intercontract/call_view_emit.0.stdout new file mode 100644 index 000000000..7d73027c8 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_view_emit.0.stdout @@ -0,0 +1 @@ +executed with `Return(null)` diff --git a/tests/cases/stable/py/intercontract/call_view_emit.0_0.hash b/tests/cases/stable/py/intercontract/call_view_emit.0_0.hash new file mode 100644 index 000000000..2cd15d6d9 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_view_emit.0_0.hash @@ -0,0 +1 @@ +LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDIOgBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwYXNzCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG1haW4oc2VsZiwgYWRkcjogQWRkcmVzcyk6CgkJIyByZWFkLW9ubHkgQ2FsbENvbnRyYWN0IGludG8gQjsgQiB0cmllcyB0byBlbWl0IGFuIGV2ZW50IGFuZCBzZW5kIGEKCQkjIG1lc3NhZ2UgaW5zaWRlIGl0LiBCb3RoIG11c3QgZmFpbCBiZWNhdXNlIHRoZSBjaGlsZCBpcyBhIHN0YXRpYyBjYWxsLgoJCXRyeToKCQkJcHJpbnQoJ0EgZ290JywgZ2wuY29udHJhY3QuZ2V0X2F0KGFkZHIpLnZpZXcoKS5waW5nKCkpCgkJZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgoJCQlwcmludChmJ0EgY2FsbCBmYWlsZWQ6IHt0eXBlKGUpLl9fbmFtZV9ffScpCgAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/intercontract/call_view_emit.0_0.stdout b/tests/cases/stable/py/intercontract/call_view_emit.0_0.stdout new file mode 100644 index 000000000..7d73027c8 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_view_emit.0_0.stdout @@ -0,0 +1 @@ +executed with `Return(null)` diff --git a/tests/cases/stable/py/intercontract/call_view_emit.0_0_0.hash b/tests/cases/stable/py/intercontract/call_view_emit.0_0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_view_emit.0_0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/intercontract/call_view_emit.0_0_0.stdout b/tests/cases/stable/py/intercontract/call_view_emit.0_0_0.stdout new file mode 100644 index 000000000..f14bfc26c --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_view_emit.0_0_0.stdout @@ -0,0 +1,4 @@ +B emit forbidden: SystemError +B send forbidden: SystemError +A got pong +executed with `Return(null)` diff --git a/tests/cases/stable/py/intercontract/call_view_emit.jsonnet b/tests/cases/stable/py/intercontract/call_view_emit.jsonnet new file mode 100644 index 000000000..6415b1489 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_view_emit.jsonnet @@ -0,0 +1,10 @@ +local simple = import 'templates/two.jsonnet'; +local util = import 'templates/util.jsonnet'; +{entry: util.addPaths([simple.run('${jsonnetDir}/call_view_emit_from.py', '${jsonnetDir}/call_view_emit_to.py', + ||| + { + "method": "main", + "args": [Address(toAddr)] + } + ||| +)])} diff --git a/tests/cases/stable/py/intercontract/call_view_emit_from.py b/tests/cases/stable/py/intercontract/call_view_emit_from.py new file mode 100644 index 000000000..aee1c07c1 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_view_emit_from.py @@ -0,0 +1,17 @@ +# { "Depends": "py-genlayer:test" } +import genlayer as gl +from genlayer.types import * + + +class Contract(gl.contract.Contract): + def __init__(self): + pass + + @gl.public.write + def main(self, addr: Address): + # read-only CallContract into B; B tries to emit an event and send a + # message inside it. Both must fail because the child is a static call. + try: + print('A got', gl.contract.get_at(addr).view().ping()) + except Exception as e: + print(f'A call failed: {type(e).__name__}') diff --git a/tests/cases/stable/py/intercontract/call_view_emit_to.py b/tests/cases/stable/py/intercontract/call_view_emit_to.py new file mode 100644 index 000000000..85bbfb545 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_view_emit_to.py @@ -0,0 +1,27 @@ +# { "Depends": "py-genlayer:test" } +import genlayer as gl +from genlayer.types import * + + +class Pinged(gl.chain.Event): + def __init__(self, who: str, /, **blob): ... + + +class Contract(gl.contract.Contract): + def __init__(self): + pass + + @gl.public.view + def ping(self) -> str: + # inside a CallContract child VM (read-only / static call) + try: + Pinged('b', note='emitted during CallContract').emit() + print('B emit: ok') + except Exception as e: + print(f'B emit forbidden: {type(e).__name__}') + try: + gl.contract.get_at(gl.Address(b'\x30' * 20)).emit().foo(1, 2) + print('B send: ok') + except Exception as e: + print(f'B send forbidden: {type(e).__name__}') + return 'pong' From 8cb5a767bc2eb387fe7dff65e68fa4013fef7583 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 14:43:24 +0900 Subject: [PATCH 066/124] =?UTF-8?q?docs(spec):=20CallContract=20preserves?= =?UTF-8?q?=20sender=5Faddress;=20immediate=20caller=20is=20stack[-1]=20?= =?UTF-8?q?=F0=9F=93=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/spec/04-contract-interface/05-execution-flow.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/website/src/spec/04-contract-interface/05-execution-flow.rst b/doc/website/src/spec/04-contract-interface/05-execution-flow.rst index 72208c602..9f2b7132c 100644 --- a/doc/website/src/spec/04-contract-interface/05-execution-flow.rst +++ b/doc/website/src/spec/04-contract-interface/05-execution-flow.rst @@ -79,3 +79,12 @@ Extended-Message Format pub entry_stage_data: calldata::Value, } + +``CallContract`` semantics +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``CallContract`` performs a read-only (view) call into another contract. It **preserves** ``sender_address`` and ``origin_address``: the callee observes the *same* ``sender_address`` as the caller did, **not** the address of the immediate caller. + +The immediate caller — the contract that issued the ``CallContract`` — is pushed onto ``stack`` instead, so the callee always sees it as ``stack[-1]`` (the last element). For the top-level entrypoint ``stack`` is empty (refer to ``contract_address``); each nested ``CallContract`` appends one entry. + +Therefore a callee that needs to authorize its *immediate* caller MUST inspect ``stack[-1]`` rather than ``sender_address`` — the latter identifies the original transaction sender shared across the whole view-call chain. From 013027cd5a28b1e521d14870aed7de98c57f13fe Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 15:08:08 +0900 Subject: [PATCH 067/124] =?UTF-8?q?docs(impl-spec):=20document=20executor?= =?UTF-8?q?=20has=20no=20timeout,=20killed=20by=20manager=20=F0=9F=93=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../02-host-interface.rst | 5 ++-- .../01-core-architecture/04-executor.rst | 30 +++++++++++++++++++ .../impl-spec/01-core-architecture/index.rst | 1 + 3 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 doc/website/src/impl-spec/01-core-architecture/04-executor.rst diff --git a/doc/website/src/impl-spec/01-core-architecture/02-host-interface.rst b/doc/website/src/impl-spec/01-core-architecture/02-host-interface.rst index 97d1fcb81..72b95d5bd 100644 --- a/doc/website/src/impl-spec/01-core-architecture/02-host-interface.rst +++ b/doc/website/src/impl-spec/01-core-architecture/02-host-interface.rst @@ -22,9 +22,8 @@ GenVM Execution **Process Control**: -- **Graceful Shutdown**: Send ``SIGTERM`` signal -- **Force Termination**: Send ``SIGKILL`` if not responding -- **Crash Detection**: Process exit before sending result indicates crash (should be reported as bug) +- **Termination**: The executor has no internal timeout or graceful-shutdown path and may be killed at any moment with ``SIGKILL`` (see :doc:`04-executor`). Timeouts are enforced by the :term:`Manager`. +- **Crash Detection**: Process exit before sending result indicates a kill/timeout or a crash (a crash should be reported as a bug) **Node Responsibilities**: Node decides how to receive code and messages from users. GenVM only knows about calldata and message data. diff --git a/doc/website/src/impl-spec/01-core-architecture/04-executor.rst b/doc/website/src/impl-spec/01-core-architecture/04-executor.rst new file mode 100644 index 000000000..e36629325 --- /dev/null +++ b/doc/website/src/impl-spec/01-core-architecture/04-executor.rst @@ -0,0 +1,30 @@ +Executor +======== + +The executor (the ``genvm`` binary) runs a single contract execution to +completion and writes its result back to the :term:`Host`. It is a short-lived, +stateless process that the :term:`Manager` spawns once per execution. + +No Internal Timeout +------------------- + +The executor does **not** implement any execution timeout, deadline, or signal +handling of its own. It runs until the contract finishes — producing a +``Return``, ``UserError``, or ``VMError`` result — or until it is terminated +externally. + +Timeouts are enforced entirely by the :term:`Manager`, which owns the executor +process lifecycle. When an execution exceeds its budget (or must otherwise be +stopped), the manager kills the executor process directly with ``SIGKILL``. The +executor installs no signal handlers and has no graceful-shutdown path, so it +**can be killed at any moment**, between any two operations, without notice. + +Implications +----------- + +- The executor keeps no durable state of its own. All persistent state lives in + the host and is written only as part of delivering a result. A killed executor + simply produces no result, which the manager treats as a failed / timed-out + execution. +- Executor code must not rely on running cleanup, flushing buffers, or + cancellation logic during shutdown — there is no shutdown to hook into. diff --git a/doc/website/src/impl-spec/01-core-architecture/index.rst b/doc/website/src/impl-spec/01-core-architecture/index.rst index 96fe82009..af000fbfe 100644 --- a/doc/website/src/impl-spec/01-core-architecture/index.rst +++ b/doc/website/src/impl-spec/01-core-architecture/index.rst @@ -9,3 +9,4 @@ Overview of GenVM's core architectural components and design patterns. 01-components 02-host-interface 03-modules/index + 04-executor From 7b4134bc1016c3a6d70c713c6626990ed20e6330 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 15:08:08 +0900 Subject: [PATCH 068/124] =?UTF-8?q?chore(executor):=20remove=20graceful-sh?= =?UTF-8?q?utdown=20signal/cancellation=20dead=20code=20=F0=9F=94=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/Cargo.lock | 11 ------ executor/Cargo.toml | 1 - executor/src/exe/run.rs | 12 ------- executor/src/lib.rs | 52 +++++++-------------------- executor/src/modules.rs | 14 ++------ executor/src/rt/mod.rs | 1 - executor/src/rt/supervisor/actions.rs | 34 ++---------------- executor/src/rt/supervisor/mod.rs | 11 +++--- executor/src/rt/vm/mod.rs | 27 -------------- 9 files changed, 22 insertions(+), 141 deletions(-) diff --git a/executor/Cargo.lock b/executor/Cargo.lock index 0a531bd0b..f1a0232e7 100644 --- a/executor/Cargo.lock +++ b/executor/Cargo.lock @@ -1027,7 +1027,6 @@ dependencies = [ "serde_with", "serde_yaml", "sha3", - "signal-hook", "symbol_table", "tokio", "tokio-mpmc", @@ -2142,16 +2141,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "signal-hook" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" -dependencies = [ - "libc", - "signal-hook-registry", -] - [[package]] name = "signal-hook-registry" version = "1.4.2" diff --git a/executor/Cargo.toml b/executor/Cargo.toml index c7a49b2ae..6814eeb25 100644 --- a/executor/Cargo.toml +++ b/executor/Cargo.toml @@ -49,7 +49,6 @@ clap = { version = "4.5.35", features = ["derive"] } serde_with = { version = "3.12.0", features = ["base64"] } itertools = "0.14.0" zip = "4.0.0" -signal-hook = "0.3.17" once_cell = "1.21.3" chrono = { version = "0.4.41", default-features = false, features = ["clock", "std", "serde"] } base64 = "0.22.1" diff --git a/executor/src/exe/run.rs b/executor/src/exe/run.rs index e7a0354c0..a00463611 100644 --- a/executor/src/exe/run.rs +++ b/executor/src/exe/run.rs @@ -85,17 +85,6 @@ pub fn handle(args: Args, mut config: config::Config) -> Result<()> { .create_rt() .with_context(|| "creating tokio runtime")?; - let (token, canceller) = genvm_common::cancellation::make(); - - let handle_sigterm = move || { - log_warn!("sigterm received"); - canceller(); - }; - unsafe { - signal_hook::low_level::register(signal_hook::consts::SIGTERM, handle_sigterm.clone())?; - signal_hook::low_level::register(signal_hook::consts::SIGINT, handle_sigterm)?; - } - let genvm_id = match &args.genvm_id { None => { let mut random_bytes = [0; 8]; @@ -152,7 +141,6 @@ pub fn handle(args: Args, mut config: config::Config) -> Result<()> { ); let shared_data = sync::DArc::new(genvm::rt::SharedData { - cancellation: token, is_sync: args.sync, genvm_id: genvm_modules_interfaces::GenVMId(genvm_id), debug_mode: args.debug_mode, diff --git a/executor/src/lib.rs b/executor/src/lib.rs index 2a7ffa49f..c1e9057f0 100644 --- a/executor/src/lib.rs +++ b/executor/src/lib.rs @@ -93,7 +93,6 @@ pub fn create_supervisor( gas_data: named.gas_data.clone(), initial_time_units_allocation: named.initial_time_units_allocation, }, - shared_data.cancellation.clone(), shared_data.genvm_id, role, host_data.clone(), @@ -106,7 +105,6 @@ pub fn create_supervisor( gas_data: named.gas_data, initial_time_units_allocation: named.initial_time_units_allocation, }, - shared_data.cancellation.clone(), shared_data.genvm_id, role, host_data, @@ -256,21 +254,7 @@ pub async fn run_with( (Ok(res), Ok(c)) => Ok((res, c)), }; - let res = if supervisor.shared_data.cancellation.is_cancelled() { - match merged_result { - Ok(mut r) => { - if r.0.kind == public_abi::ResultCode::VmError { - r.0.data = calldata::Value::Str(public_abi::VmError::timeout().0.into()).into(); - } - Ok(r) - } - Err(_e) => Ok((rt::vm::FullResult::timeout(), None)), - } - } else { - merged_result - }; - - let res = res.inspect_err(|e| { + let res = merged_result.inspect_err(|e| { log_error!(error:ah = &e; "internal error"); }); @@ -285,28 +269,18 @@ pub async fn run_with( log_debug!("all executions done, collecting stats"); - let is_timeout = supervisor.shared_data.cancellation.is_cancelled(); - - let web_metrics = if is_timeout { - None - } else { - supervisor - .modules - .web - .get_stats(genvm_modules_interfaces::web::Message::GetStats) - .await - .ok() - }; - let llm_metrics = if is_timeout { - None - } else { - supervisor - .modules - .llm - .get_stats(genvm_modules_interfaces::llm::Message::GetStats) - .await - .ok() - }; + let web_metrics = supervisor + .modules + .web + .get_stats(genvm_modules_interfaces::web::Message::GetStats) + .await + .ok(); + let llm_metrics = supervisor + .modules + .llm + .get_stats(genvm_modules_interfaces::llm::Message::GetStats) + .await + .ok(); #[derive(serde::Serialize)] struct AllMetrics<'a> { diff --git a/executor/src/modules.rs b/executor/src/modules.rs index abd3f1545..91acfe726 100644 --- a/executor/src/modules.rs +++ b/executor/src/modules.rs @@ -17,7 +17,6 @@ struct ModuleImpl { pub struct Module { name: String, - cancellation: Arc, imp: tokio::sync::Mutex, genvm_id: genvm_modules_interfaces::GenVMId, role: genvm_modules_interfaces::Role, @@ -100,7 +99,6 @@ pub struct ModuleNamedArgs { impl Module { pub fn new( named: ModuleNamedArgs, - cancellation: Arc, genvm_id: genvm_modules_interfaces::GenVMId, role: genvm_modules_interfaces::Role, host_data: genvm_modules_interfaces::HostData, @@ -111,7 +109,6 @@ impl Module { url: named.url, stream: None, }), - cancellation, genvm_id, role, name: named.name, @@ -222,14 +219,9 @@ impl Module { V: calldata::codec::Encode, Error = std::convert::Infallible>, R: calldata::codec::Decode, { - tokio::select! { - _ = self.cancellation.chan.closed() => { - anyhow::bail!("timeout") // it will be replaced later - } - res = self.send_impl(val) => { - res.with_context(|| "sending request to module") - } - } + self.send_impl(val) + .await + .with_context(|| "sending request to module") } } diff --git a/executor/src/rt/mod.rs b/executor/src/rt/mod.rs index 7c4280bc8..4722b2c3d 100644 --- a/executor/src/rt/mod.rs +++ b/executor/src/rt/mod.rs @@ -48,7 +48,6 @@ impl DetNondet { /// basic data that is shared across all VMs pub struct SharedData { - pub cancellation: Arc, pub is_sync: bool, pub genvm_id: genvm_modules_interfaces::GenVMId, pub debug_mode: bool, diff --git a/executor/src/rt/supervisor/actions.rs b/executor/src/rt/supervisor/actions.rs index 454df3dab..dd3929051 100644 --- a/executor/src/rt/supervisor/actions.rs +++ b/executor/src/rt/supervisor/actions.rs @@ -254,7 +254,6 @@ pub(crate) async fn load_runner( pub(crate) fn map_archive_file( preview1: &mut crate::wasi::preview1::Context, limiter: &rt::memlimiter::Limiter, - cancellation: &genvm_common::cancellation::Token, arch: &runners::ArchiveCache, file: &str, to: &str, @@ -271,10 +270,6 @@ pub(crate) fn map_archive_file( let must_start_with: &str = if is_root { "" } else { file }; for (name, file_contents) in range { - if cancellation.is_cancelled() { - return Err(rt::errors::VMError(public_abi::VmError::timeout(), None).into()); - } - if name.ends_with("/") { continue; } @@ -341,14 +336,7 @@ pub(crate) async fn map_runner_file( runner, ) .await?; - map_archive_file( - preview1, - limiter, - &supervisor.shared_data.cancellation, - &arch, - path_in_runner, - path_in_vfs, - ) + map_archive_file(preview1, limiter, &arch, path_in_runner, path_in_vfs) } impl Ctx<'_, '_> { @@ -467,23 +455,11 @@ impl Ctx<'_, '_> { ) -> anyhow::Result> { use runners::InitAction; - if self.supervisor.shared_data.cancellation.is_cancelled() { - return Err(rt::errors::VMError(public_abi::VmError::timeout(), None).into()); - } - match action { InitAction::MapFile { to, file } => { let limiter = self.vm.store.data_mut().limits.clone(); - let cancellation = self.supervisor.shared_data.cancellation.clone(); let preview1 = &mut self.vm.store.data_mut().genlayer_ctx_mut().preview1; - map_archive_file( - preview1, - &limiter, - &cancellation, - current_runner_arch, - file, - to, - )?; + map_archive_file(preview1, &limiter, current_runner_arch, file, to)?; Ok(None) } InitAction::AddEnv { name, val } => { @@ -586,12 +562,6 @@ impl Ctx<'_, '_> { } InitAction::Seq(vec) => { for act in vec { - if self.supervisor.shared_data.cancellation.is_cancelled() { - return Err( - rt::errors::VMError(public_abi::VmError::timeout(), None).into() - ); - } - if let Some(x) = Box::pin(self.apply(act, current, current_runner_arch)).await? { return Ok(Some(x)); diff --git a/executor/src/rt/supervisor/mod.rs b/executor/src/rt/supervisor/mod.rs index 97e9fd479..48b1d062c 100644 --- a/executor/src/rt/supervisor/mod.rs +++ b/executor/src/rt/supervisor/mod.rs @@ -352,10 +352,12 @@ pub async fn spawn( error: anyhow::Error::from(a), state: Box::new(rt::SpawnErrorState::Unspawned(b)), })?, - supervisor: zelf.clone(), }, wasmtime::GenVMCtx { - should_quit: zelf.shared_data.cancellation.should_quit.clone(), + // The executor has no cooperative cancellation; the manager kills the + // process on timeout. wasmtime still requires this flag, so feed it a + // never-set atomic. + should_quit: std::sync::Arc::new(std::sync::atomic::AtomicU32::new(0)), }, ); @@ -573,11 +575,6 @@ async fn nondet_vm_processor( let mut count = 0; loop { tokio::select! { - _ = zelf.shared_data.cancellation.chan.closed() => { - log_debug!("cancellation requested, stopping nondet validator queue"); - break; - } - _ = zelf.queue.vm_countdown.wait() => { log_debug!("vm countdown reached zero, stopping nondet validator queue"); break; diff --git a/executor/src/rt/vm/mod.rs b/executor/src/rt/vm/mod.rs index 51a0a3b02..a8656f1a8 100644 --- a/executor/src/rt/vm/mod.rs +++ b/executor/src/rt/vm/mod.rs @@ -144,7 +144,6 @@ impl std::fmt::Display for RunOk { pub struct WasmtimeStoreData { pub(super) genlayer_ctx: wasi::Context, pub(super) limits: rt::memlimiter::Limiter, - pub(super) supervisor: std::sync::Arc, } impl WasmtimeStoreData { @@ -221,32 +220,6 @@ impl VM { let wasm_store_hashes = self.vm_base.wasm_store_hashes(); - let res = if self - .vm_base - .store - .data() - .supervisor - .shared_data - .cancellation - .is_cancelled() - { - match res { - Ok((rt::vm::RunOk::VMError(msg, cause), backtrace)) => Ok(( - rt::vm::RunOk::VMError( - public_abi::VmError::timeout(), - cause.map(|v| v.context(msg.0)), - ), - backtrace, - )), - Ok(r) => Ok(r), - Err(e) => Ok(( - rt::vm::RunOk::VMError(public_abi::VmError::timeout(), Some(e)), - None, - )), - } - } else { - res - }; match &res { Ok((rt::vm::RunOk::Return(_), _)) => { log_debug!(result = "Return"; "execution result unwrapped") From c87be55c28ef503761677d2a947e235e1505b560 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 15:11:19 +0900 Subject: [PATCH 069/124] =?UTF-8?q?docs(spec):=20RunNondet=20disables=20re?= =?UTF-8?q?gister=5Frunners;=20link=20permission=20spec=20from=20code=20?= =?UTF-8?q?=F0=9F=93=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/website/src/spec/03-vm/05-permissions.rst | 1 + executor/src/lib.rs | 1 + executor/src/rt/supervisor/mod.rs | 4 ++++ executor/src/wasi/genlayer_sdk.rs | 3 +++ 4 files changed, 9 insertions(+) diff --git a/doc/website/src/spec/03-vm/05-permissions.rst b/doc/website/src/spec/03-vm/05-permissions.rst index f0438b681..1435ec1d1 100644 --- a/doc/website/src/spec/03-vm/05-permissions.rst +++ b/doc/website/src/spec/03-vm/05-permissions.rst @@ -87,6 +87,7 @@ The non-deterministic :term:`sub-VM` has: - :ref:`gvm-perm-spawn-nondet` is **disabled** - :ref:`gvm-perm-call-others` is **disabled** - :ref:`gvm-perm-send-messages` is **disabled** +- :ref:`gvm-perm-register-runners` is **disabled** ``Sandbox`` ~~~~~~~~~~~ diff --git a/executor/src/lib.rs b/executor/src/lib.rs index c1e9057f0..e4e3a7214 100644 --- a/executor/src/lib.rs +++ b/executor/src/lib.rs @@ -177,6 +177,7 @@ pub async fn run_with_impl( let essential_data = Box::new(wasi::genlayer_sdk::SingleVMData { depth: 0, + // Permission model: doc/website/src/spec/03-vm/05-permissions.rst conf: wasi::base::Config { needs_error_fingerprint: true, is_deterministic: true, diff --git a/executor/src/rt/supervisor/mod.rs b/executor/src/rt/supervisor/mod.rs index 48b1d062c..63bc387a2 100644 --- a/executor/src/rt/supervisor/mod.rs +++ b/executor/src/rt/supervisor/mod.rs @@ -149,6 +149,10 @@ pub async fn await_nondet_vms(zelf: &Arc) -> anyhow::Result { let vm_data = Box::new(SingleVMData { depth: self.context.data.depth + 1, + // Permission model: doc/website/src/spec/03-vm/05-permissions.rst conf: base::Config { needs_error_fingerprint: true, is_deterministic: true, @@ -1759,6 +1760,7 @@ impl ContextVFS<'_> { let vm_data = Box::new(SingleVMData { depth: self.context.data.depth + 1, + // Permission model: doc/website/src/spec/03-vm/05-permissions.rst conf: base::Config { needs_error_fingerprint: false, is_deterministic: false, @@ -1850,6 +1852,7 @@ impl ContextVFS<'_> { let vm_data = Box::new(SingleVMData { depth: self.context.data.depth + 1, + // Permission model: doc/website/src/spec/03-vm/05-permissions.rst conf: base::Config { needs_error_fingerprint: false, is_deterministic: zelf_conf.is_deterministic, From 8caba68a6f889fbddbf38bd54a534e900c6de94e Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 15:15:55 +0900 Subject: [PATCH 070/124] =?UTF-8?q?feat(executor):=20assert=20discarded=20?= =?UTF-8?q?CallContract=20accumulator=20is=20empty=20=F0=9F=94=92=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/src/wasi/genlayer_sdk.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/executor/src/wasi/genlayer_sdk.rs b/executor/src/wasi/genlayer_sdk.rs index dc3332164..81594f3b1 100644 --- a/executor/src/wasi/genlayer_sdk.rs +++ b/executor/src/wasi/genlayer_sdk.rs @@ -250,6 +250,22 @@ pub struct VMDataAccumulator { pub message_fee_allocation: Vec, } +impl VMDataAccumulator { + /// Asserts the accumulator carries no surfaced effects (events, + /// message-fee allocations). Call it after running a sub-VM whose + /// accumulator is discarded (e.g. a `CallContract` child) to guarantee no + /// effect was charged but silently dropped. Returns a fatal error otherwise. + pub fn check_empty(&self) -> anyhow::Result<()> { + anyhow::ensure!( + self.emissions.is_empty() && self.message_fee_allocation.is_empty(), + "internal error: discarded sub-VM accumulator is not empty ({} emission(s), {} message-fee allocation(s))", + self.emissions.len(), + self.message_fee_allocation.len(), + ); + Ok(()) + } +} + pub struct SingleVMData { pub conf: base::Config, pub depth: u32, @@ -770,6 +786,13 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { .await .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?; + // The child is read-only (static), so its accumulator must be + // empty — otherwise an effect was charged but discarded here. + res.vm_data + .accumulator + .check_empty() + .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?; + let hash = res.small_hash(); self.context.data.det_subvm_hashes.update(&hash); From eceeb7af4ebf5bf78f9e43e492e186cff1202954 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 15:25:43 +0900 Subject: [PATCH 071/124] =?UTF-8?q?docs(spec):=20CallContract=20reads=20co?= =?UTF-8?q?mmitted=20state,=20not=20in-tx=20delta=20+=20test=20?= =?UTF-8?q?=F0=9F=93=9D=E2=9C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../05-execution-flow.rst | 7 ++++ .../call_view_committed.0.stdout | 1 + .../call_view_committed.0_0.stdout | 2 ++ .../intercontract/call_view_committed.jsonnet | 3 ++ .../py/intercontract/call_view_committed.py | 35 +++++++++++++++++++ 5 files changed, 48 insertions(+) create mode 100644 tests/cases/stable/py/intercontract/call_view_committed.0.stdout create mode 100644 tests/cases/stable/py/intercontract/call_view_committed.0_0.stdout create mode 100644 tests/cases/stable/py/intercontract/call_view_committed.jsonnet create mode 100644 tests/cases/stable/py/intercontract/call_view_committed.py diff --git a/doc/website/src/spec/04-contract-interface/05-execution-flow.rst b/doc/website/src/spec/04-contract-interface/05-execution-flow.rst index 9f2b7132c..5ba584229 100644 --- a/doc/website/src/spec/04-contract-interface/05-execution-flow.rst +++ b/doc/website/src/spec/04-contract-interface/05-execution-flow.rst @@ -88,3 +88,10 @@ Extended-Message Format The immediate caller — the contract that issued the ``CallContract`` — is pushed onto ``stack`` instead, so the callee always sees it as ``stack[-1]`` (the last element). For the top-level entrypoint ``stack`` is empty (refer to ``contract_address``); each nested ``CallContract`` appends one entry. Therefore a callee that needs to authorize its *immediate* caller MUST inspect ``stack[-1]`` rather than ``sender_address`` — the latter identifies the original transaction sender shared across the whole view-call chain. + +State visibility +"""""""""""""""" + +A ``CallContract`` child reads **committed** on-chain storage (the latest accepted / non-final state); it does **not** see the calling transaction's uncommitted writes. Consequently a contract does not observe its own in-transaction storage delta through a ``CallContract`` — including a self-call ``get_at(self.address)`` — even though a *direct* read does. + +This is intentional: it preserves causality and avoids exposing stale-then-fresh reads within one call. It is also a footgun: relying on a self-``CallContract`` to read state written earlier in the same transaction returns the old value. Use direct reads for in-transaction data, and treat ``get_at(self.address)`` as a read of the committed snapshot only. diff --git a/tests/cases/stable/py/intercontract/call_view_committed.0.stdout b/tests/cases/stable/py/intercontract/call_view_committed.0.stdout new file mode 100644 index 000000000..7d73027c8 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_view_committed.0.stdout @@ -0,0 +1 @@ +executed with `Return(null)` diff --git a/tests/cases/stable/py/intercontract/call_view_committed.0_0.stdout b/tests/cases/stable/py/intercontract/call_view_committed.0_0.stdout new file mode 100644 index 000000000..c56221105 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_view_committed.0_0.stdout @@ -0,0 +1,2 @@ +[1, 1, 1, 30, 1, 30] +executed with `Return(null)` diff --git a/tests/cases/stable/py/intercontract/call_view_committed.jsonnet b/tests/cases/stable/py/intercontract/call_view_committed.jsonnet new file mode 100644 index 000000000..250bafa08 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_view_committed.jsonnet @@ -0,0 +1,3 @@ +local simple_deploy_then_write = import 'templates/simple_deploy_then_write.jsonnet'; +local util = import 'templates/util.jsonnet'; +{entry: util.addPaths([simple_deploy_then_write.run('${jsonnetDir}/${fileBaseName}.py', 'do_test')])} diff --git a/tests/cases/stable/py/intercontract/call_view_committed.py b/tests/cases/stable/py/intercontract/call_view_committed.py new file mode 100644 index 000000000..e8afa6609 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_view_committed.py @@ -0,0 +1,35 @@ +# { "Depends": "py-genlayer:test" } +import genlayer as gl +from genlayer.types import * + + +class Contract(gl.contract.Contract): + x: u32 + write_answer: gl.DynArray[u32] + + def __init__(self): + self.x = u32(1) + + @gl.public.view + def do_read(self) -> u32: + return self.x + + @gl.public.write + def do_test(self): + # A direct read sees the in-transaction delta; a CallContract (view) reads + # committed on-chain state and does NOT see the uncommitted write below. + self.write_answer.append(self.do_read()) # 1 + self.write_answer.append( + gl.contract.get_at(self.address).view().do_read() + ) # 1 (committed) + self.write_answer.append(self.do_read()) # 1 + + self.x = u32(30) + + self.write_answer.append(self.do_read()) # 30 (delta) + self.write_answer.append( + gl.contract.get_at(self.address).view().do_read() + ) # 1 (committed) + self.write_answer.append(self.do_read()) # 30 + + print(list(self.write_answer)) From 26404c99e2ab52a2b6c4cb1458fed07afec2776c Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 15:28:36 +0900 Subject: [PATCH 072/124] =?UTF-8?q?test(intercontract):=20drop=20committed?= =?UTF-8?q?=20execution=20hashes=20(run=20with=20--ignore-hash)=20?= =?UTF-8?q?=F0=9F=94=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/cases/stable/py/intercontract/call_view_emit.0.hash | 1 - tests/cases/stable/py/intercontract/call_view_emit.0_0.hash | 1 - tests/cases/stable/py/intercontract/call_view_emit.0_0_0.hash | 1 - 3 files changed, 3 deletions(-) delete mode 100644 tests/cases/stable/py/intercontract/call_view_emit.0.hash delete mode 100644 tests/cases/stable/py/intercontract/call_view_emit.0_0.hash delete mode 100644 tests/cases/stable/py/intercontract/call_view_emit.0_0_0.hash diff --git a/tests/cases/stable/py/intercontract/call_view_emit.0.hash b/tests/cases/stable/py/intercontract/call_view_emit.0.hash deleted file mode 100644 index 7d38b1914..000000000 --- a/tests/cases/stable/py/intercontract/call_view_emit.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDLK0CAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIFBpbmdlZChnbC5jaGFpbi5FdmVudCk6CglkZWYgX19pbml0X18oc2VsZiwgd2hvOiBzdHIsIC8sICoqYmxvYik6IC4uLgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwYXNzCgoJQGdsLnB1YmxpYy52aWV3CglkZWYgcGluZyhzZWxmKSAtPiBzdHI6CgkJIyBpbnNpZGUgYSBDYWxsQ29udHJhY3QgY2hpbGQgVk0gKHJlYWQtb25seSAvIHN0YXRpYyBjYWxsKQoJCXRyeToKCQkJUGluZ2VkKCdiJywgbm90ZT0nZW1pdHRlZCBkdXJpbmcgQ2FsbENvbnRyYWN0JykuZW1pdCgpCgkJCXByaW50KCdCIGVtaXQ6IG9rJykKCQlleGNlcHQgRXhjZXB0aW9uIGFzIGU6CgkJCXByaW50KGYnQiBlbWl0IGZvcmJpZGRlbjoge3R5cGUoZSkuX19uYW1lX199JykKCQl0cnk6CgkJCWdsLmNvbnRyYWN0LmdldF9hdChnbC5BZGRyZXNzKGInXHgzMCcgKiAyMCkpLmVtaXQoKS5mb28oMSwgMikKCQkJcHJpbnQoJ0Igc2VuZDogb2snKQoJCWV4Y2VwdCBFeGNlcHRpb24gYXMgZToKCQkJcHJpbnQoZidCIHNlbmQgZm9yYmlkZGVuOiB7dHlwZShlKS5fX25hbWVfX30nKQoJCXJldHVybiAncG9uZycKAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/intercontract/call_view_emit.0_0.hash b/tests/cases/stable/py/intercontract/call_view_emit.0_0.hash deleted file mode 100644 index 2cd15d6d9..000000000 --- a/tests/cases/stable/py/intercontract/call_view_emit.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDIOgBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwYXNzCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG1haW4oc2VsZiwgYWRkcjogQWRkcmVzcyk6CgkJIyByZWFkLW9ubHkgQ2FsbENvbnRyYWN0IGludG8gQjsgQiB0cmllcyB0byBlbWl0IGFuIGV2ZW50IGFuZCBzZW5kIGEKCQkjIG1lc3NhZ2UgaW5zaWRlIGl0LiBCb3RoIG11c3QgZmFpbCBiZWNhdXNlIHRoZSBjaGlsZCBpcyBhIHN0YXRpYyBjYWxsLgoJCXRyeToKCQkJcHJpbnQoJ0EgZ290JywgZ2wuY29udHJhY3QuZ2V0X2F0KGFkZHIpLnZpZXcoKS5waW5nKCkpCgkJZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgoJCQlwcmludChmJ0EgY2FsbCBmYWlsZWQ6IHt0eXBlKGUpLl9fbmFtZV9ffScpCgAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/intercontract/call_view_emit.0_0_0.hash b/tests/cases/stable/py/intercontract/call_view_emit.0_0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/intercontract/call_view_emit.0_0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF From 3fc17fc0369e55451d6a6cd3f85addd4640dcd03 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 15:38:14 +0900 Subject: [PATCH 073/124] =?UTF-8?q?fix(executor):=20write=20contract=20maj?= =?UTF-8?q?or=20on=20deploy=20alongside=20code=20=F0=9F=90=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/src/lib.rs | 5 +++++ executor/src/rt/vm/storage.rs | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/executor/src/lib.rs b/executor/src/lib.rs index e4e3a7214..6c3f73d3b 100644 --- a/executor/src/lib.rs +++ b/executor/src/lib.rs @@ -169,6 +169,11 @@ pub async fn run_with_impl( log_debug!("using provided code for execution"); topmost_storage.write_code(code).await?; + // Record the major this contract is deployed for, so later runs can + // verify major compatibility (see `read_major` / major_mismatch check). + topmost_storage + .write_major(genvm_common::version::CURRENT.major as u8) + .await?; } else { log_debug!("code is null"); } diff --git a/executor/src/rt/vm/storage.rs b/executor/src/rt/vm/storage.rs index 6b31d40fa..8c86b2b97 100644 --- a/executor/src/rt/vm/storage.rs +++ b/executor/src/rt/vm/storage.rs @@ -421,6 +421,14 @@ impl Storage { Ok(buf[0]) } + /// Writes the GenVM major version the contract is deployed for into the + /// `major` root field, so later runs can verify major compatibility (see + /// [`read_major`]). Written on deploy alongside the code. + pub async fn write_major(&mut self, major: u8) -> anyhow::Result<()> { + self.write(SlotID::ZERO, root_offsets::MAJOR, &[major]) + .await + } + /// Resolves the slot the contract code is stored at: the raw `code_slot` root /// field if set, otherwise the default `code` slot. pub async fn resolve_code_slot(&mut self) -> anyhow::Result { From 9d415ee1db63ed80f1365bcd15d98c5b8cd119a6 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 15:40:03 +0900 Subject: [PATCH 074/124] =?UTF-8?q?test(intercontract):=20self-CallContrac?= =?UTF-8?q?t=20(incl.=20in=20deploy)=20is=20allowed=20=E2=80=94=20footgun?= =?UTF-8?q?=20=E2=9C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../py/intercontract/call_self_view.0.stdout | 1 + .../intercontract/call_self_view.0_0.stdout | 2 ++ .../py/intercontract/call_self_view.jsonnet | 3 +++ .../stable/py/intercontract/call_self_view.py | 21 +++++++++++++++++++ .../call_self_view_init.0.stdout | 2 ++ .../intercontract/call_self_view_init.jsonnet | 3 +++ .../py/intercontract/call_self_view_init.py | 17 +++++++++++++++ 7 files changed, 49 insertions(+) create mode 100644 tests/cases/stable/py/intercontract/call_self_view.0.stdout create mode 100644 tests/cases/stable/py/intercontract/call_self_view.0_0.stdout create mode 100644 tests/cases/stable/py/intercontract/call_self_view.jsonnet create mode 100644 tests/cases/stable/py/intercontract/call_self_view.py create mode 100644 tests/cases/stable/py/intercontract/call_self_view_init.0.stdout create mode 100644 tests/cases/stable/py/intercontract/call_self_view_init.jsonnet create mode 100644 tests/cases/stable/py/intercontract/call_self_view_init.py diff --git a/tests/cases/stable/py/intercontract/call_self_view.0.stdout b/tests/cases/stable/py/intercontract/call_self_view.0.stdout new file mode 100644 index 000000000..7d73027c8 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_self_view.0.stdout @@ -0,0 +1 @@ +executed with `Return(null)` diff --git a/tests/cases/stable/py/intercontract/call_self_view.0_0.stdout b/tests/cases/stable/py/intercontract/call_self_view.0_0.stdout new file mode 100644 index 000000000..986740094 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_self_view.0_0.stdout @@ -0,0 +1,2 @@ +self view -> 30 +executed with `Return(null)` diff --git a/tests/cases/stable/py/intercontract/call_self_view.jsonnet b/tests/cases/stable/py/intercontract/call_self_view.jsonnet new file mode 100644 index 000000000..55c663b38 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_self_view.jsonnet @@ -0,0 +1,3 @@ +local simple_deploy_then_write = import 'templates/simple_deploy_then_write.jsonnet'; +local util = import 'templates/util.jsonnet'; +{entry: util.addPaths([simple_deploy_then_write.run('${jsonnetDir}/${fileBaseName}.py', 'main')])} diff --git a/tests/cases/stable/py/intercontract/call_self_view.py b/tests/cases/stable/py/intercontract/call_self_view.py new file mode 100644 index 000000000..0f632fe54 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_self_view.py @@ -0,0 +1,21 @@ +# { "Depends": "py-genlayer:test" } +import genlayer as gl +from genlayer.types import * + + +class Contract(gl.contract.Contract): + def __init__(self): + pass + + @gl.public.view + def read30(self) -> u32: + return u32(30) + + @gl.public.write + def main(self): + # self-CallContract into our own view method; arguably a re-entrancy + # footgun that should be forbidden + try: + print('self view ->', gl.contract.get_at(self.address).view().read30()) + except Exception as e: + print('self view failed:', type(e).__name__) diff --git a/tests/cases/stable/py/intercontract/call_self_view_init.0.stdout b/tests/cases/stable/py/intercontract/call_self_view_init.0.stdout new file mode 100644 index 000000000..986740094 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_self_view_init.0.stdout @@ -0,0 +1,2 @@ +self view -> 30 +executed with `Return(null)` diff --git a/tests/cases/stable/py/intercontract/call_self_view_init.jsonnet b/tests/cases/stable/py/intercontract/call_self_view_init.jsonnet new file mode 100644 index 000000000..0e1c4ba55 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_self_view_init.jsonnet @@ -0,0 +1,3 @@ +local simple_deploy = import 'templates/simple_deploy.jsonnet'; +local util = import 'templates/util.jsonnet'; +{entry: util.addPaths([simple_deploy.run('${jsonnetDir}/${fileBaseName}.py')])} diff --git a/tests/cases/stable/py/intercontract/call_self_view_init.py b/tests/cases/stable/py/intercontract/call_self_view_init.py new file mode 100644 index 000000000..d5d6389b5 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_self_view_init.py @@ -0,0 +1,17 @@ +# { "Depends": "py-genlayer:test" } +import genlayer as gl +from genlayer.types import * + + +class Contract(gl.contract.Contract): + def __init__(self): + # self-CallContract during deploy, before this contract is committed; + # arguably should be forbidden + try: + print('self view ->', gl.contract.get_at(self.address).view().read30()) + except Exception as e: + print('self view failed:', type(e).__name__) + + @gl.public.view + def read30(self) -> u32: + return u32(30) From 8f401a7ddc422216fa475f8b4b04f5891b59ad7f Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 15:41:08 +0900 Subject: [PATCH 075/124] =?UTF-8?q?perf(wasi):=20skip=20trace=20message=20?= =?UTF-8?q?timing/logging=20when=20not=20in=20debug=20mode=20=E2=9A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/src/wasi/genlayer_sdk.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/executor/src/wasi/genlayer_sdk.rs b/executor/src/wasi/genlayer_sdk.rs index 81594f3b1..0b8a205d5 100644 --- a/executor/src/wasi/genlayer_sdk.rs +++ b/executor/src/wasi/genlayer_sdk.rs @@ -1539,6 +1539,12 @@ impl ContextVFS<'_> { ) -> Result { match msg { gl_call::TracePayload::Message(text) => { + // Tracing is a debug-only aid; skip the timing and logging work + // entirely when not in debug mode. + if !self.context.data.supervisor.shared_data.debug_mode { + return Ok(file_fd_none()); + } + let now = std::time::Instant::now(); let since_prev = now.duration_since(self.context.prev_time); self.context.prev_time = now; From de9d69a9d660df356f8a53ff073e08c08d972fbc Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 15:45:02 +0900 Subject: [PATCH 076/124] =?UTF-8?q?test(intercontract):=20self-CallContrac?= =?UTF-8?q?t=20in=20=5F=5Finit=5F=5F=20(deploy)=20is=20allowed=20=E2=80=94?= =?UTF-8?q?=20footgun=20=E2=9C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../py/intercontract/call_self_view.0.stdout | 1 + .../py/intercontract/call_self_view.0_0.stdout | 2 -- .../py/intercontract/call_self_view.jsonnet | 4 ++-- .../stable/py/intercontract/call_self_view.py | 14 +++++--------- .../intercontract/call_self_view_init.0.stdout | 2 -- .../intercontract/call_self_view_init.jsonnet | 3 --- .../py/intercontract/call_self_view_init.py | 17 ----------------- 7 files changed, 8 insertions(+), 35 deletions(-) delete mode 100644 tests/cases/stable/py/intercontract/call_self_view.0_0.stdout delete mode 100644 tests/cases/stable/py/intercontract/call_self_view_init.0.stdout delete mode 100644 tests/cases/stable/py/intercontract/call_self_view_init.jsonnet delete mode 100644 tests/cases/stable/py/intercontract/call_self_view_init.py diff --git a/tests/cases/stable/py/intercontract/call_self_view.0.stdout b/tests/cases/stable/py/intercontract/call_self_view.0.stdout index 7d73027c8..986740094 100644 --- a/tests/cases/stable/py/intercontract/call_self_view.0.stdout +++ b/tests/cases/stable/py/intercontract/call_self_view.0.stdout @@ -1 +1,2 @@ +self view -> 30 executed with `Return(null)` diff --git a/tests/cases/stable/py/intercontract/call_self_view.0_0.stdout b/tests/cases/stable/py/intercontract/call_self_view.0_0.stdout deleted file mode 100644 index 986740094..000000000 --- a/tests/cases/stable/py/intercontract/call_self_view.0_0.stdout +++ /dev/null @@ -1,2 +0,0 @@ -self view -> 30 -executed with `Return(null)` diff --git a/tests/cases/stable/py/intercontract/call_self_view.jsonnet b/tests/cases/stable/py/intercontract/call_self_view.jsonnet index 55c663b38..0e1c4ba55 100644 --- a/tests/cases/stable/py/intercontract/call_self_view.jsonnet +++ b/tests/cases/stable/py/intercontract/call_self_view.jsonnet @@ -1,3 +1,3 @@ -local simple_deploy_then_write = import 'templates/simple_deploy_then_write.jsonnet'; +local simple_deploy = import 'templates/simple_deploy.jsonnet'; local util = import 'templates/util.jsonnet'; -{entry: util.addPaths([simple_deploy_then_write.run('${jsonnetDir}/${fileBaseName}.py', 'main')])} +{entry: util.addPaths([simple_deploy.run('${jsonnetDir}/${fileBaseName}.py')])} diff --git a/tests/cases/stable/py/intercontract/call_self_view.py b/tests/cases/stable/py/intercontract/call_self_view.py index 0f632fe54..931b28767 100644 --- a/tests/cases/stable/py/intercontract/call_self_view.py +++ b/tests/cases/stable/py/intercontract/call_self_view.py @@ -5,17 +5,13 @@ class Contract(gl.contract.Contract): def __init__(self): - pass - - @gl.public.view - def read30(self) -> u32: - return u32(30) - - @gl.public.write - def main(self): - # self-CallContract into our own view method; arguably a re-entrancy + # self-CallContract into our own view method during deploy; arguably a # footgun that should be forbidden try: print('self view ->', gl.contract.get_at(self.address).view().read30()) except Exception as e: print('self view failed:', type(e).__name__) + + @gl.public.view + def read30(self) -> int: + return 30 diff --git a/tests/cases/stable/py/intercontract/call_self_view_init.0.stdout b/tests/cases/stable/py/intercontract/call_self_view_init.0.stdout deleted file mode 100644 index 986740094..000000000 --- a/tests/cases/stable/py/intercontract/call_self_view_init.0.stdout +++ /dev/null @@ -1,2 +0,0 @@ -self view -> 30 -executed with `Return(null)` diff --git a/tests/cases/stable/py/intercontract/call_self_view_init.jsonnet b/tests/cases/stable/py/intercontract/call_self_view_init.jsonnet deleted file mode 100644 index 0e1c4ba55..000000000 --- a/tests/cases/stable/py/intercontract/call_self_view_init.jsonnet +++ /dev/null @@ -1,3 +0,0 @@ -local simple_deploy = import 'templates/simple_deploy.jsonnet'; -local util = import 'templates/util.jsonnet'; -{entry: util.addPaths([simple_deploy.run('${jsonnetDir}/${fileBaseName}.py')])} diff --git a/tests/cases/stable/py/intercontract/call_self_view_init.py b/tests/cases/stable/py/intercontract/call_self_view_init.py deleted file mode 100644 index d5d6389b5..000000000 --- a/tests/cases/stable/py/intercontract/call_self_view_init.py +++ /dev/null @@ -1,17 +0,0 @@ -# { "Depends": "py-genlayer:test" } -import genlayer as gl -from genlayer.types import * - - -class Contract(gl.contract.Contract): - def __init__(self): - # self-CallContract during deploy, before this contract is committed; - # arguably should be forbidden - try: - print('self view ->', gl.contract.get_at(self.address).view().read30()) - except Exception as e: - print('self view failed:', type(e).__name__) - - @gl.public.view - def read30(self) -> u32: - return u32(30) From a67ab6abe8607a69bde4f610619b7e1c51bb2482 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 15:46:23 +0900 Subject: [PATCH 077/124] =?UTF-8?q?test(intercontract):=20simplify=20call?= =?UTF-8?q?=5Fview=5Fcommitted=20literals=20=F0=9F=8E=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/cases/stable/py/intercontract/call_view_committed.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/cases/stable/py/intercontract/call_view_committed.py b/tests/cases/stable/py/intercontract/call_view_committed.py index e8afa6609..e7f2b2f98 100644 --- a/tests/cases/stable/py/intercontract/call_view_committed.py +++ b/tests/cases/stable/py/intercontract/call_view_committed.py @@ -8,7 +8,7 @@ class Contract(gl.contract.Contract): write_answer: gl.DynArray[u32] def __init__(self): - self.x = u32(1) + self.x = 1 @gl.public.view def do_read(self) -> u32: @@ -24,7 +24,7 @@ def do_test(self): ) # 1 (committed) self.write_answer.append(self.do_read()) # 1 - self.x = u32(30) + self.x = 30 self.write_answer.append(self.do_read()) # 30 (delta) self.write_answer.append( From d4bc56d128872a38864a61b75bda20b666079446 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 15:50:08 +0900 Subject: [PATCH 078/124] =?UTF-8?q?fix(manager):=20bound=20per-execution?= =?UTF-8?q?=20log=20sink=20unless=20debug=20mode=20=F0=9F=94=92=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/implementation/src/common/mod.rs | 36 ++++++++++++++++++++++- modules/implementation/src/manager/run.rs | 7 +++-- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/modules/implementation/src/common/mod.rs b/modules/implementation/src/common/mod.rs index bd31a41da..cb8439c4d 100644 --- a/modules/implementation/src/common/mod.rs +++ b/modules/implementation/src/common/mod.rs @@ -943,7 +943,41 @@ impl LogSinkElement { } } -pub type LogSink = Arc>; +/// Maximum number of buffered log entries kept per execution when not in debug +/// mode; older entries are evicted to bound memory usage. +pub const LOG_SINK_LIMIT: usize = 128; + +#[derive(Default)] +pub struct LogSinkInner { + queue: crossbeam::queue::SegQueue, + debug: bool, +} + +impl LogSinkInner { + pub fn new(debug: bool) -> Self { + Self { + queue: crossbeam::queue::SegQueue::new(), + debug, + } + } + + /// Appends an entry. In debug mode the sink is unbounded; otherwise the + /// oldest entries are dropped to keep at most [`LOG_SINK_LIMIT`] buffered. + pub fn push(&self, elem: LogSinkElement) { + if !self.debug { + while self.queue.len() >= LOG_SINK_LIMIT { + self.queue.pop(); + } + } + self.queue.push(elem); + } + + pub fn pop(&self) -> Option { + self.queue.pop() + } +} + +pub type LogSink = Arc; pub static GENVM_BY_ID_LOGGER: std::sync::LazyLock< papaya::HashMap, diff --git a/modules/implementation/src/manager/run.rs b/modules/implementation/src/manager/run.rs index a92cf63c2..6bc32cb1f 100644 --- a/modules/implementation/src/manager/run.rs +++ b/modules/implementation/src/manager/run.rs @@ -11,7 +11,7 @@ use tokio::io::AsyncBufReadExt; pub use genvm_modules_interfaces::GenVMId; -use crate::common::{LogSink, LogSinkElement, LoggerWithId, GENVM_BY_ID_LOGGER}; +use crate::common::{LogSink, LogSinkElement, LogSinkInner, LoggerWithId, GENVM_BY_ID_LOGGER}; /// Spawn relay that passes the stream to the module handler async fn spawn_module_relay( @@ -911,7 +911,10 @@ pub async fn start_genvm( ctx.permits.clone().acquire_owned().await? }; - let log_sink: LogSink = Arc::new(Default::default()); + // Debug executions (passing `--debug-mode` to the executor) keep all logs; + // otherwise the sink is bounded to avoid unbounded per-execution growth. + let debug_mode = req.extra_args.iter().any(|a| a == "--debug-mode"); + let log_sink: LogSink = Arc::new(LogSinkInner::new(debug_mode)); GENVM_BY_ID_LOGGER.pin().insert(genvm_id, log_sink.clone()); let log_sink_guard = sync::DropGuard::new(|| { GENVM_BY_ID_LOGGER.pin().remove(&genvm_id); From 1731c7138f0cc04a4d435fa6ca927b30fec5035f Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 16:40:03 +0900 Subject: [PATCH 079/124] =?UTF-8?q?feat(executor):=20configurable=20debug?= =?UTF-8?q?=5Fmode=20with=20Capture,=20replacing=20capture=5Foutput=20?= =?UTF-8?q?=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/crates/common/src/debug_mode.rs | 100 ++++++++++++++++++ executor/crates/common/src/lib.rs | 2 + executor/src/exe/run.rs | 6 +- executor/src/rt/mod.rs | 2 +- executor/src/rt/supervisor/actions.rs | 4 +- executor/src/rt/supervisor/mod.rs | 2 +- executor/src/wasi/genlayer_sdk.rs | 17 ++- modules/implementation/src/manager/run.rs | 88 +++++++++++---- support/scripts/compile-py.py | 2 +- tests/runner/origin/base_host.py | 4 +- .../ya_test_runner_plugins/integration.py | 3 +- .../runner/ya_test_runner_plugins/permits.py | 4 +- 12 files changed, 200 insertions(+), 34 deletions(-) create mode 100644 executor/crates/common/src/debug_mode.rs diff --git a/executor/crates/common/src/debug_mode.rs b/executor/crates/common/src/debug_mode.rs new file mode 100644 index 000000000..0aee8c128 --- /dev/null +++ b/executor/crates/common/src/debug_mode.rs @@ -0,0 +1,100 @@ +use serde::{Deserialize, Serialize}; + +/// How the manager captures a per-execution's logs and stdout/stderr. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize)] +#[serde(rename_all = "kebab-case")] +pub enum Capture { + /// Nothing is captured: stdout/stderr go to `/dev/null` and logs are routed + /// to the manager's own log. + #[default] + Disabled, + /// Captured, but bounded: the oldest log entries are dropped past a cap and + /// stdout/stderr are truncated to a tail. + Bounded, + /// Captured in full. + Unbounded, +} + +/// Executor debug level. Levels are ordered and each *adds* to the previous one. +/// +/// - `Disabled`: production. No capture, no debug aids. +/// - `Safe`: captures logs and stdout/stderr (bounded). Deterministic. +/// - `SafeUnbounded`: capture is unbounded and `Trace` gl_call output is emitted. +/// Deterministic. +/// - `Unsafe`: also resolves the `:latest` / `:test` runner ids. This is +/// *unsafe across machines* — different nodes may resolve different code — so +/// it can diverge consensus, but a single node stays deterministic. +/// - `UnsafeTracing`: also exposes real wall-clock time to the contract +/// (`RuntimeMicroSec`). This can break determinism even on a single machine. +/// Local debugging only. +#[derive( + Debug, + Clone, + Copy, + PartialEq, + Eq, + PartialOrd, + Ord, + Default, + clap::ValueEnum, + Serialize, + Deserialize, + ::genlayer_calldata::Encode, + ::genlayer_calldata::Decode, +)] +#[clap(rename_all = "kebab-case")] +#[serde(rename_all = "kebab-case")] +pub enum DebugMode { + #[default] + #[calldata(rename = "disabled")] + Disabled, + #[calldata(rename = "safe")] + Safe, + #[calldata(rename = "safe-unbounded")] + SafeUnbounded, + #[calldata(rename = "unsafe")] + Unsafe, + #[calldata(rename = "unsafe-tracing")] + UnsafeTracing, +} + +impl DebugMode { + /// How the manager should capture logs and stdout/stderr. + pub fn capture(self) -> Capture { + match self { + DebugMode::Disabled => Capture::Disabled, + DebugMode::Safe => Capture::Bounded, + DebugMode::SafeUnbounded | DebugMode::Unsafe | DebugMode::UnsafeTracing => { + Capture::Unbounded + } + } + } + + /// `SafeUnbounded`+: emit `Trace` gl_call output instead of skipping it. + pub fn allows_tracing(self) -> bool { + self >= DebugMode::SafeUnbounded + } + + /// `Unsafe`+: the `:latest` / `:test` runner ids may be resolved. Unsafe + /// across machines (consensus may diverge). + pub fn allows_latest_resolution(self) -> bool { + self >= DebugMode::Unsafe + } + + /// `UnsafeTracing`: exposes non-deterministic data to the contract, such as + /// real wall-clock time metering. Can break determinism on a single machine. + pub fn allows_nondeterminism(self) -> bool { + self >= DebugMode::UnsafeTracing + } + + /// CLI value passed to the executor's `--debug-mode` flag. + pub fn as_arg(self) -> &'static str { + match self { + DebugMode::Disabled => "disabled", + DebugMode::Safe => "safe", + DebugMode::SafeUnbounded => "safe-unbounded", + DebugMode::Unsafe => "unsafe", + DebugMode::UnsafeTracing => "unsafe-tracing", + } + } +} diff --git a/executor/crates/common/src/lib.rs b/executor/crates/common/src/lib.rs index a29f5b5a7..ed150c507 100644 --- a/executor/crates/common/src/lib.rs +++ b/executor/crates/common/src/lib.rs @@ -9,6 +9,8 @@ pub mod bytes32; pub use bytes32::Bytes32Hash; pub mod cancellation; +pub mod debug_mode; +pub use debug_mode::DebugMode; pub mod io; pub mod logger; pub mod stats; diff --git a/executor/src/exe/run.rs b/executor/src/exe/run.rs index a00463611..baca5092e 100644 --- a/executor/src/exe/run.rs +++ b/executor/src/exe/run.rs @@ -17,9 +17,11 @@ const EXECUTION_DATA_HELP: &str = "path to file containing encoded execution dat pub struct Args { #[arg( long, - help = "whenever to allow `:latest` and `:test` as runners version, tracing, etc." + value_enum, + default_value = "disabled", + help = "debug level: disabled|safe|full|full-unsafe. safe+ allows `:latest`/`:test` runners and tracing; full-unsafe additionally exposes non-deterministic data such as real time metering" )] - debug_mode: bool, + debug_mode: genvm_common::DebugMode, #[arg(long, default_value = "-", help = EXECUTION_DATA_HELP)] execution_data: String, diff --git a/executor/src/rt/mod.rs b/executor/src/rt/mod.rs index 4722b2c3d..641cf6220 100644 --- a/executor/src/rt/mod.rs +++ b/executor/src/rt/mod.rs @@ -50,7 +50,7 @@ impl DetNondet { pub struct SharedData { pub is_sync: bool, pub genvm_id: genvm_modules_interfaces::GenVMId, - pub debug_mode: bool, + pub debug_mode: genvm_common::DebugMode, pub metrics: crate::Metrics, pub data_fees_limit: fees::DataLimit, pub llm_consumption: tokio::sync::Mutex, diff --git a/executor/src/rt/supervisor/actions.rs b/executor/src/rt/supervisor/actions.rs index dd3929051..e0fd25c57 100644 --- a/executor/src/rt/supervisor/actions.rs +++ b/executor/src/rt/supervisor/actions.rs @@ -95,7 +95,7 @@ fn resolve_runner( runners::IdUnresolved::Contract => unreachable!("contract is resolved to chain"), runners::IdUnresolved::Builtin { name, hash } => { let hash: Bytes32Hash = if hash.as_str() == "test" { - if !supervisor.shared_data.debug_mode { + if !supervisor.shared_data.debug_mode.allows_latest_resolution() { log_warn!(":test runner used in non-debug mode, this is not allowed"); return Err(make_malformed_runner_error( "runner id doesn't match expected format", @@ -103,7 +103,7 @@ fn resolve_runner( } runners::TEST_RUNNER_HASH } else if hash.as_str() == "latest" { - if !supervisor.shared_data.debug_mode { + if !supervisor.shared_data.debug_mode.allows_latest_resolution() { log_warn!(":latest runner used in non-debug mode, this is not allowed"); return Err(make_malformed_runner_error( "runner id doesn't match expected format", diff --git a/executor/src/rt/supervisor/mod.rs b/executor/src/rt/supervisor/mod.rs index 63bc387a2..effdb2d31 100644 --- a/executor/src/rt/supervisor/mod.rs +++ b/executor/src/rt/supervisor/mod.rs @@ -303,7 +303,7 @@ impl Supervisor { runner_cache: runners::cache::Reader::new( std::path::Path::new(&config.runners_dir), std::path::Path::new(&config.registry_dir), - debug_mode, + debug_mode.allows_latest_resolution(), ) .context("creating runner cache reader")?, wasm_mod_cache: WasmModuleCache { diff --git a/executor/src/wasi/genlayer_sdk.rs b/executor/src/wasi/genlayer_sdk.rs index 0b8a205d5..2d6c99830 100644 --- a/executor/src/wasi/genlayer_sdk.rs +++ b/executor/src/wasi/genlayer_sdk.rs @@ -1541,7 +1541,14 @@ impl ContextVFS<'_> { gl_call::TracePayload::Message(text) => { // Tracing is a debug-only aid; skip the timing and logging work // entirely when not in debug mode. - if !self.context.data.supervisor.shared_data.debug_mode { + if !self + .context + .data + .supervisor + .shared_data + .debug_mode + .allows_tracing() + { return Ok(file_fd_none()); } @@ -1560,7 +1567,13 @@ impl ContextVFS<'_> { } gl_call::TracePayload::RuntimeMicroSec => { let elapsed_micros = if self.context.data.conf.is_deterministic - && !self.context.data.supervisor.shared_data.debug_mode + && !self + .context + .data + .supervisor + .shared_data + .debug_mode + .allows_nondeterminism() { 0u64 } else { diff --git a/modules/implementation/src/manager/run.rs b/modules/implementation/src/manager/run.rs index 6bc32cb1f..700e23410 100644 --- a/modules/implementation/src/manager/run.rs +++ b/modules/implementation/src/manager/run.rs @@ -1,5 +1,5 @@ use std::{ - ops::{Deref, DerefMut}, + ops::DerefMut, os::fd::{AsRawFd, FromRawFd}, str::FromStr, sync::Arc, @@ -372,6 +372,10 @@ fn default_extra_args() -> Vec { Vec::new() } +fn default_debug_mode() -> genvm_common::DebugMode { + genvm_common::DebugMode::Disabled +} + fn default_no_modules() -> bool { false } @@ -384,7 +388,12 @@ pub struct Request { pub major: u32, pub message: genvm_common::domain::MessageData, pub is_sync: bool, - pub capture_output: bool, + /// Executor debug level. Controls runner `:latest`/`:test` resolution, + /// tracing, captured-output bounding, and (under `full-unsafe`) exposing + /// non-deterministic data. See `genvm_common::DebugMode`. + #[serde(default)] + #[calldata(default = default_debug_mode)] + pub debug_mode: genvm_common::DebugMode, #[serde(default = "default_max_execution_minutes")] #[calldata(default = default_max_execution_minutes)] pub max_execution_minutes: u64, @@ -452,9 +461,11 @@ trait LogAppender { async fn append_text(&mut self, serde_err: serde_json::Error, text: &str); } +/// Used when capture is `disabled`: forwards the executor's logs to the +/// manager's own log instead of buffering them into the result. struct LogAppenderToLog(GenVMId); -impl Deref for LogAppenderToLog { +impl std::ops::Deref for LogAppenderToLog { type Target = Self; fn deref(&self) -> &Self::Target { @@ -546,10 +557,28 @@ async fn read_log_pipe( Ok(()) } +/// Maximum bytes of stdout/stderr kept (as a tail) per execution when not in +/// debug mode, to bound manager memory. +const OUTPUT_TAIL_LIMIT: usize = 4 * 1024 * 1024; + +/// Keeps only the last `limit` bytes of `s`, trimming whole UTF-8 chars from the +/// front (so the most recent output survives). +fn keep_tail(s: &mut String, limit: usize) { + if s.len() <= limit { + return; + } + let mut cut = s.len() - limit; + while cut < s.len() && !s.is_char_boundary(cut) { + cut += 1; + } + s.drain(..cut); +} + async fn pipe_read( mut reader: P, to: sync::DArc>, permit: tokio::sync::OwnedSemaphorePermit, + max_bytes: Option, ) { let mut result = String::new(); let mut buf = vec![0u8; 8192]; @@ -576,6 +605,13 @@ async fn pipe_read( result.push_str(&s); } } + + // Bound memory while reading: keep only the tail when not in debug mode. + if let Some(limit) = max_bytes { + if result.len() > limit { + keep_tail(&mut result, limit); + } + } } if let Err(e) = to.set(result) { @@ -750,12 +786,15 @@ fn build_genvm_command( proc.arg(format!("--genvm-id={}", genvm_id.0)); - if req.capture_output { - proc.stdout(std::process::Stdio::piped()); - proc.stderr(std::process::Stdio::piped()); - } else { + proc.arg("--debug-mode"); + proc.arg(req.debug_mode.as_arg()); + + if req.debug_mode.capture() == genvm_common::debug_mode::Capture::Disabled { proc.stdout(std::process::Stdio::null()); proc.stderr(std::process::Stdio::null()); + } else { + proc.stdout(std::process::Stdio::piped()); + proc.stderr(std::process::Stdio::piped()); } proc @@ -911,10 +950,11 @@ pub async fn start_genvm( ctx.permits.clone().acquire_owned().await? }; - // Debug executions (passing `--debug-mode` to the executor) keep all logs; - // otherwise the sink is bounded to avoid unbounded per-execution growth. - let debug_mode = req.extra_args.iter().any(|a| a == "--debug-mode"); - let log_sink: LogSink = Arc::new(LogSinkInner::new(debug_mode)); + // Capture controls how logs and stdout/stderr are kept: disabled (forwarded + // to the manager log only), bounded, or unbounded. + use genvm_common::debug_mode::Capture; + let capture = req.debug_mode.capture(); + let log_sink: LogSink = Arc::new(LogSinkInner::new(capture == Capture::Unbounded)); GENVM_BY_ID_LOGGER.pin().insert(genvm_id, log_sink.clone()); let log_sink_guard = sync::DropGuard::new(|| { GENVM_BY_ID_LOGGER.pin().remove(&genvm_id); @@ -975,17 +1015,18 @@ pub async fn start_genvm( let execution_data_bytes = bytes::Bytes::from(execution_data_bytes); - // Spawn log reader - if req.capture_output { + // Spawn log reader: capture into the sink, or (when capture is disabled) + // forward to the manager log instead of buffering into the result. + if capture == Capture::Disabled { + tokio::spawn(read_log_pipe(read_fd, LogAppenderToLog(genvm_id))); + } else { let logger = Arc::new(tokio::sync::Mutex::new(LogAppenderToValue( log_sink.clone(), genvm_id, ))); let l = logger.clone().lock_owned().await; tokio::spawn(read_log_pipe(read_fd, l)); - } else { - tokio::spawn(read_log_pipe(read_fd, LogAppenderToLog(genvm_id))); - }; + } // Spawn child process, then drop child-side FDs let mut child = proc.spawn()?; @@ -1043,11 +1084,22 @@ pub async fn start_genvm( spawn_stdin_monitor(stdin_task, exec_ctx.clone(), genvm_id); } + let out_limit = (capture == Capture::Bounded).then_some(OUTPUT_TAIL_LIMIT); if let Some(stdout) = stdout { - tokio::spawn(pipe_read(stdout, exec_ctx.gep(|x| &x.stdout), stdout_perm)); + tokio::spawn(pipe_read( + stdout, + exec_ctx.gep(|x| &x.stdout), + stdout_perm, + out_limit, + )); } if let Some(stderr) = stderr { - tokio::spawn(pipe_read(stderr, exec_ctx.gep(|x| &x.stderr), stderr_perm)); + tokio::spawn(pipe_read( + stderr, + exec_ctx.gep(|x| &x.stderr), + stderr_perm, + out_limit, + )); } ctx.known_executions diff --git a/support/scripts/compile-py.py b/support/scripts/compile-py.py index 615256ba4..b5e28915a 100755 --- a/support/scripts/compile-py.py +++ b/support/scripts/compile-py.py @@ -149,7 +149,7 @@ async def compile_py(src: Path, out: Path, manager_url: str) -> None: host='unix://' + sock_path, code=COMPILER_CONTRACT.encode('utf-8'), calldata=calldata, - extra_args=['--debug-mode'], + debug_mode='unsafe', ) if res.result_kind != public_abi.ResultCode.RETURN: diff --git a/tests/runner/origin/base_host.py b/tests/runner/origin/base_host.py index cfc35f24a..3e0c4f5ce 100644 --- a/tests/runner/origin/base_host.py +++ b/tests/runner/origin/base_host.py @@ -448,7 +448,7 @@ async def run_genvm( manager_uri: str = 'http://127.0.0.1:3999', ctx: Context, is_sync: bool, - capture_output: bool = True, + debug_mode: str = 'disabled', message: Message, host_data: str = '', gas_data: dict[str, str] | None = None, @@ -493,7 +493,7 @@ async def wrap_proc_body(attempt: int): 'major': 0, # FIXME 'message': message, 'is_sync': is_sync, - 'capture_output': capture_output, + 'debug_mode': debug_mode, 'host_data': host_data, 'max_execution_minutes': max_exec_mins, # this parameter is needed to prevent zombie genvms 'timestamp': timestamp, diff --git a/tests/runner/ya_test_runner_plugins/integration.py b/tests/runner/ya_test_runner_plugins/integration.py index 3e1b6897c..c7d10f121 100644 --- a/tests/runner/ya_test_runner_plugins/integration.py +++ b/tests/runner/ya_test_runner_plugins/integration.py @@ -602,12 +602,11 @@ async def _run_single_step( manager_uri=manager_uri, message=single_conf['message'], timeout=single_conf.get('deadline', 10 * 60), - capture_output=True, is_sync=(mode == 's'), host_data=host_data, ctx=ctx, host='unix://' + mock_host.path, - extra_args=['--debug-mode'], + debug_mode='unsafe', code=code, calldata=calldata_bytes, bucket_totals=bucket_totals, diff --git a/tests/runner/ya_test_runner_plugins/permits.py b/tests/runner/ya_test_runner_plugins/permits.py index 3a411ab9e..afd818887 100644 --- a/tests/runner/ya_test_runner_plugins/permits.py +++ b/tests/runner/ya_test_runner_plugins/permits.py @@ -190,14 +190,13 @@ async def _run_background_genvm( manager_uri=manager_uri, ctx=ctx, is_sync=True, - capture_output=True, message=FAKE_MESSAGE, host_data='{"node_address":"test","tx_id":"test"}', host='unix://' + sock_path, code=code, calldata=gvm_calldata.encode({}), timeout=300, - extra_args=['--debug-mode'], + debug_mode='unsafe', request_extra={'no_modules': True}, shutdown_early=shut_downer, ) @@ -211,7 +210,6 @@ async def _assert_blocks(self, manager_uri: str, code: bytes) -> bool: 'major': 0, 'message': FAKE_MESSAGE, 'is_sync': True, - 'capture_output': True, 'host_data': '{"node_address":"test","tx_id":"test"}', 'max_execution_minutes': 20, 'timestamp': '2024-11-26T06:42:42.424242Z', From 995b807d461e26b4550bc47bedb469a962e3caa6 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 16:40:04 +0900 Subject: [PATCH 080/124] =?UTF-8?q?docs(impl-spec):=20document=20debug=5Fm?= =?UTF-8?q?ode=20levels=20+=20Capture;=20drop=20capture=5Foutput=20?= =?UTF-8?q?=F0=9F=93=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../01-core-architecture/04-executor.rst | 63 +++++++++++++++++++ .../src/impl-spec/appendix/manager-api.yaml | 17 +++-- 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/doc/website/src/impl-spec/01-core-architecture/04-executor.rst b/doc/website/src/impl-spec/01-core-architecture/04-executor.rst index e36629325..8eba11044 100644 --- a/doc/website/src/impl-spec/01-core-architecture/04-executor.rst +++ b/doc/website/src/impl-spec/01-core-architecture/04-executor.rst @@ -28,3 +28,66 @@ Implications execution. - Executor code must not rely on running cleanup, flushing buffers, or cancellation logic during shutdown — there is no shutdown to hook into. + +Debug modes +----------- + +The debug level is a top-level field of the manager ``run`` request +(``debug_mode``), forwarded to the executor as ``--debug-mode ``. The +default is ``disabled``. + +Output **capture** is a derived property with three states: + +- ``disabled`` — nothing is captured into the result: the executor's + stdout/stderr go to ``/dev/null`` and its logs are *forwarded to the manager's + own log* (so they are not lost, just not returned in the response). +- ``bounded`` — captured into the result, but bounded: at most the 128 most + recent log entries are kept (oldest dropped), and stdout/stderr are truncated + to a 4 MiB tail each. +- ``unbounded`` — captured into the result in full. + +When capture is ``disabled`` the result's log/stdout/stderr fields are empty +(empty list / empty strings), not omitted; ``bounded`` and ``unbounded`` use the +same field shapes, differing only in how much they contain. + +The levels are ordered; each *adds* to the previous one: + +.. list-table:: + :header-rows: 1 + :widths: 20 22 58 + + * - Level + - Capture + - Adds + * - ``disabled`` + - ``disabled`` + - Production default. Logs are forwarded to the manager log; no result capture; no debug aids. + * - ``safe`` + - ``bounded`` + - Logs and stdout/stderr are captured into the result (bounded). Deterministic. + * - ``safe-unbounded`` + - ``unbounded`` + - Capture becomes unbounded and ``Trace`` gl_call output is emitted. Deterministic. + * - ``unsafe`` + - ``unbounded`` + - The ``:latest`` / ``:test`` runner ids may be resolved. **Unsafe across machines**: different nodes may resolve different code and diverge consensus, though a single node stays deterministic. + * - ``unsafe-tracing`` + - ``unbounded`` + - Real wall-clock time is exposed to the contract (``RuntimeMicroSec`` returns actual elapsed time instead of ``0``). **Can break determinism on a single machine.** Local debugging only. + +Only ``unsafe`` and ``unsafe-tracing`` can affect determinism (across machines +and on a single machine respectively); ``safe`` and ``safe-unbounded`` are fully +consensus-safe (``safe-unbounded`` deliberately couples unbounded capture with +``Trace`` emission — both are deterministic, verbose debug aids). In code these +distinctions are methods on ``genvm_common::DebugMode``: ``capture()`` (returns +the ``Capture`` state), ``allows_tracing()``, ``allows_latest_resolution()``, +and ``allows_nondeterminism()``. + +**Enforcement.** ``debug_mode`` is a per-request field, so on a consensus +network the manager MUST reject (or clamp to a configured maximum) ``unsafe`` +and ``unsafe-tracing`` from untrusted callers — otherwise a single request could +force ``:latest``/``:test`` resolution (cross-node divergence) or expose real +time (single-machine non-determinism). Unbounded capture (``safe-unbounded`` and +above) also trades the memory bound for completeness, so operators should treat +the higher levels as privileged. An unrecognized ``debug_mode`` value is +rejected rather than silently downgraded. diff --git a/doc/website/src/impl-spec/appendix/manager-api.yaml b/doc/website/src/impl-spec/appendix/manager-api.yaml index f21fcc5e0..fdae60607 100644 --- a/doc/website/src/impl-spec/appendix/manager-api.yaml +++ b/doc/website/src/impl-spec/appendix/manager-api.yaml @@ -617,7 +617,6 @@ components: - major - message - is_sync - - capture_output - storage_pages - host_data - timestamp @@ -633,9 +632,19 @@ components: is_sync: type: boolean description: Whether execution is synchronous - capture_output: - type: boolean - description: Whether to capture execution output + debug_mode: + type: string + default: disabled + enum: [disabled, safe, safe-unbounded, unsafe, unsafe-tracing] + description: | + Executor debug level (see the Executor "Debug modes" section). Each level + adds to the previous one. Replaces the former `capture_output` boolean, + from which the output `Capture` (disabled/bounded/unbounded) is now derived. + + On a consensus network the manager MUST reject (or clamp) `unsafe` and + `unsafe-tracing` from untrusted callers: `unsafe` enables `:latest`/`:test` + resolution (different nodes may diverge) and `unsafe-tracing` exposes real + time (breaks single-machine determinism). An unrecognized value is rejected. max_execution_minutes: type: integer format: uint64 From f97f120a0c336cc7e4d9bd54c73daa2f7f1d7e55 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 16:44:05 +0900 Subject: [PATCH 081/124] =?UTF-8?q?docs(spec):=20fix=20RuntimeMicroSec=20d?= =?UTF-8?q?et-mode=20override=20+=20stale=20debug=20level=20names=20?= =?UTF-8?q?=F0=9F=93=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/impl-spec/01-core-architecture/04-executor.rst | 2 +- .../03-wasi_genlayer_sdk/02-gl_call.rst | 2 +- executor/src/exe/run.rs | 2 +- modules/implementation/src/manager/run.rs | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/website/src/impl-spec/01-core-architecture/04-executor.rst b/doc/website/src/impl-spec/01-core-architecture/04-executor.rst index 8eba11044..a5fb25194 100644 --- a/doc/website/src/impl-spec/01-core-architecture/04-executor.rst +++ b/doc/website/src/impl-spec/01-core-architecture/04-executor.rst @@ -73,7 +73,7 @@ The levels are ordered; each *adds* to the previous one: - The ``:latest`` / ``:test`` runner ids may be resolved. **Unsafe across machines**: different nodes may resolve different code and diverge consensus, though a single node stays deterministic. * - ``unsafe-tracing`` - ``unbounded`` - - Real wall-clock time is exposed to the contract (``RuntimeMicroSec`` returns actual elapsed time instead of ``0``). **Can break determinism on a single machine.** Local debugging only. + - Real wall-clock time is exposed to the contract in deterministic mode (``RuntimeMicroSec`` returns actual elapsed time instead of ``0``; non-deterministic mode already returns real time regardless of debug level). **Can break determinism on a single machine.** Local debugging only. Only ``unsafe`` and ``unsafe-tracing`` can affect determinism (across machines and on a single machine respectively); ``safe`` and ``safe-unbounded`` are fully diff --git a/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst b/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst index 5ef87f2da..d356e4f30 100644 --- a/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst +++ b/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst @@ -478,7 +478,7 @@ Requirements ------------------------------------- In :ref:`gvm-def-non-det-mode` returns the elapsed execution time in microseconds since VM start. -In :ref:`gvm-def-det-mode`, it always returns ``0``. +In :ref:`gvm-def-det-mode`, it returns ``0`` — exposing real elapsed time there would break determinism. The sole exception is the ``unsafe-tracing`` debug level (see the executor "Debug modes" section), which returns real elapsed time even in deterministic mode; that level is for local debugging only and must never be used on a consensus network. Payload ~~~~~~~ diff --git a/executor/src/exe/run.rs b/executor/src/exe/run.rs index baca5092e..7510de24d 100644 --- a/executor/src/exe/run.rs +++ b/executor/src/exe/run.rs @@ -19,7 +19,7 @@ pub struct Args { long, value_enum, default_value = "disabled", - help = "debug level: disabled|safe|full|full-unsafe. safe+ allows `:latest`/`:test` runners and tracing; full-unsafe additionally exposes non-deterministic data such as real time metering" + help = "debug level: disabled|safe|safe-unbounded|unsafe|unsafe-tracing. safe captures (bounded); safe-unbounded adds unbounded capture and tracing; unsafe adds `:latest`/`:test` resolution (diverges across machines); unsafe-tracing adds real time metering (non-deterministic)" )] debug_mode: genvm_common::DebugMode, diff --git a/modules/implementation/src/manager/run.rs b/modules/implementation/src/manager/run.rs index 700e23410..f8a67b0c8 100644 --- a/modules/implementation/src/manager/run.rs +++ b/modules/implementation/src/manager/run.rs @@ -388,9 +388,9 @@ pub struct Request { pub major: u32, pub message: genvm_common::domain::MessageData, pub is_sync: bool, - /// Executor debug level. Controls runner `:latest`/`:test` resolution, - /// tracing, captured-output bounding, and (under `full-unsafe`) exposing - /// non-deterministic data. See `genvm_common::DebugMode`. + /// Executor debug level. Controls captured-output bounding, tracing, runner + /// `:latest`/`:test` resolution (under `unsafe`), and (under `unsafe-tracing`) + /// exposing non-deterministic data. See `genvm_common::DebugMode`. #[serde(default)] #[calldata(default = default_debug_mode)] pub debug_mode: genvm_common::DebugMode, From d2b73491651ce76dcde42993820fa0dd4fd6018f Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 16:55:14 +0900 Subject: [PATCH 082/124] =?UTF-8?q?fix(manager):=20empty=20genvm=5Flog=20u?= =?UTF-8?q?nder=20disabled=20capture;=20test=20keep=5Ftail=20=E2=9C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/implementation/src/manager/run.rs | 41 ++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/modules/implementation/src/manager/run.rs b/modules/implementation/src/manager/run.rs index f8a67b0c8..3bbce557e 100644 --- a/modules/implementation/src/manager/run.rs +++ b/modules/implementation/src/manager/run.rs @@ -465,6 +465,9 @@ trait LogAppender { /// manager's own log instead of buffering them into the result. struct LogAppenderToLog(GenVMId); +// `read_log_pipe` takes `impl DerefMut`. The value-capturing +// appender is wrapped in `Arc>` (which derefs to it), but this +// forwarding appender holds no shared state, so it derefs to itself. impl std::ops::Deref for LogAppenderToLog { type Target = Self; @@ -955,7 +958,12 @@ pub async fn start_genvm( use genvm_common::debug_mode::Capture; let capture = req.debug_mode.capture(); let log_sink: LogSink = Arc::new(LogSinkInner::new(capture == Capture::Unbounded)); - GENVM_BY_ID_LOGGER.pin().insert(genvm_id, log_sink.clone()); + // Only route per-id logs into the result sink when we actually capture; under + // `disabled` the sink stays unregistered so manager-internal logs (and the + // forwarded executor logs) go to the manager log, leaving `genvm_log` empty. + if capture != Capture::Disabled { + GENVM_BY_ID_LOGGER.pin().insert(genvm_id, log_sink.clone()); + } let log_sink_guard = sync::DropGuard::new(|| { GENVM_BY_ID_LOGGER.pin().remove(&genvm_id); }); @@ -1109,3 +1117,34 @@ pub async fn start_genvm( Ok((genvm_id, rx)) } + +#[cfg(test)] +mod tests { + use super::keep_tail; + + #[test] + fn under_or_at_limit_is_unchanged() { + let mut s = String::from("hello"); + keep_tail(&mut s, 10); + assert_eq!(s, "hello"); + keep_tail(&mut s, 5); + assert_eq!(s, "hello"); + } + + #[test] + fn keeps_the_tail() { + let mut s = String::from("0123456789"); + keep_tail(&mut s, 4); + assert_eq!(s, "6789"); + } + + #[test] + fn never_cuts_mid_char() { + // "aéb" = a(1) é(2) b(1) = 4 bytes; cutting at byte 2 is mid-'é', so the + // cut advances to the next boundary, dropping the partial char. + let mut s = String::from("aéb"); + keep_tail(&mut s, 2); + assert_eq!(s, "b"); + assert!(std::str::from_utf8(s.as_bytes()).is_ok()); + } +} From 77b0cbc7fc0ef35ad6061efdc2faaeadac06a5e5 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 17:01:22 +0900 Subject: [PATCH 083/124] =?UTF-8?q?test(runners):=20custom=20runner=20regi?= =?UTF-8?q?stered=20in=20det=20leaks=20into=20nondet=20scope=20=E2=9C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../runners/nondet_custom_runner.0.stdout | 2 ++ .../runners/nondet_custom_runner.jsonnet | 3 +++ .../stable/runners/nondet_custom_runner.py | 25 +++++++++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 tests/cases/stable/runners/nondet_custom_runner.0.stdout create mode 100644 tests/cases/stable/runners/nondet_custom_runner.jsonnet create mode 100644 tests/cases/stable/runners/nondet_custom_runner.py diff --git a/tests/cases/stable/runners/nondet_custom_runner.0.stdout b/tests/cases/stable/runners/nondet_custom_runner.0.stdout new file mode 100644 index 000000000..1ad6a7116 --- /dev/null +++ b/tests/cases/stable/runners/nondet_custom_runner.0.stdout @@ -0,0 +1,2 @@ +nondet mapped det-registered runner (LEAK) +executed with `Return(null)` diff --git a/tests/cases/stable/runners/nondet_custom_runner.jsonnet b/tests/cases/stable/runners/nondet_custom_runner.jsonnet new file mode 100644 index 000000000..23ed8292d --- /dev/null +++ b/tests/cases/stable/runners/nondet_custom_runner.jsonnet @@ -0,0 +1,3 @@ +local simple = import 'templates/simple_deploy.jsonnet'; +local util = import 'templates/util.jsonnet'; +{entry: util.addPaths([simple.run('${jsonnetDir}/nondet_custom_runner.py') {permissions: 'rwscnu'}])} diff --git a/tests/cases/stable/runners/nondet_custom_runner.py b/tests/cases/stable/runners/nondet_custom_runner.py new file mode 100644 index 000000000..a10e87617 --- /dev/null +++ b/tests/cases/stable/runners/nondet_custom_runner.py @@ -0,0 +1,25 @@ +# { "Depends": "py-genlayer:test" } +import genlayer as gl +from genlayer.vm import register_runner, map_file + + +class Contract(gl.contract.Contract): + def __init__(self): + # deterministic context registers a custom runner + code = b'# { "Depends": "py-genlayer:test" }\nmarker\n' + rid = register_runner(code) + + def leader(): + # burn a long loop first, then try to use the det-registered custom + # runner from inside nondet. Custom runners should be scoped to the + # execution that registered them, so this map MUST fail — but with a + # shared registry it may leak. + for _ in range(10**6): + pass + try: + map_file(rid, 'file', '/mapped.txt') + return 'nondet mapped det-registered runner (LEAK)' + except Exception as e: + return f'nondet map failed: {type(e).__name__}' + + print(gl.vm.run_nondet(leader, lambda r: True)) From 6b43857e618d4c76d0c7cdf6d0b8148e7459be7a Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 18:04:32 +0900 Subject: [PATCH 084/124] =?UTF-8?q?fix(executor):=20scope=20custom=20runne?= =?UTF-8?q?rs=20per-execution;=20don't=20intern=20unvalidated=20runner=20i?= =?UTF-8?q?ds=20=F0=9F=94=92=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/src/lib.rs | 1 + executor/src/rt/supervisor/actions.rs | 29 ++++++++++++++----- executor/src/wasi/genlayer_sdk.rs | 22 +++++++++++++- .../runners/nondet_custom_runner.0.stdout | 3 +- .../stable/runners/nondet_custom_runner.py | 2 +- 5 files changed, 46 insertions(+), 11 deletions(-) diff --git a/executor/src/lib.rs b/executor/src/lib.rs index 6c3f73d3b..5b0877d53 100644 --- a/executor/src/lib.rs +++ b/executor/src/lib.rs @@ -209,6 +209,7 @@ pub async fn run_with_impl( messages_value_decremented: primitive_types::U256::zero(), emissions: Vec::new(), message_fee_allocation: entry_data.message_fee_allocation, + custom_runners: Default::default(), }, det_subvm_hashes: Default::default(), }); diff --git a/executor/src/rt/supervisor/actions.rs b/executor/src/rt/supervisor/actions.rs index e0fd25c57..362a484b3 100644 --- a/executor/src/rt/supervisor/actions.rs +++ b/executor/src/rt/supervisor/actions.rs @@ -83,9 +83,9 @@ fn resolve_runner( contract_address: calldata::Address, state: public_abi::StorageType, code_slot: crate::SlotID, - id: symbol_table::GlobalSymbol, + id: &str, ) -> anyhow::Result { - let Some(parsed) = runners::parse_runner_id(id.as_str()) else { + let Some(parsed) = runners::parse_runner_id(id) else { return Err(make_malformed_runner_error( "runner id doesn't match expected format", )); @@ -233,18 +233,31 @@ async fn get_arch( /// Resolves and loads a runner archive by id. Shared entry point used by both /// contract initialization and runtime `gl_call`s. +#[allow(clippy::too_many_arguments)] pub(crate) async fn load_runner( supervisor: &rt::supervisor::Supervisor, contract_address: calldata::Address, state: public_abi::StorageType, code_slot: crate::SlotID, limiter: &rt::memlimiter::Limiter, - id: symbol_table::GlobalSymbol, + id: &str, + available_custom: &rpds::HashTrieSet, ) -> anyhow::Result<( symbol_table::GlobalSymbol, sync::DArc, )> { let resolved = resolve_runner(supervisor, contract_address, state, code_slot, id)?; + // Custom runners are execution-scoped: a `custom:` is only resolvable + // by a scope that registered it (or inherited it from a det parent), so the + // shared registry cannot leak a runner across unrelated scopes (e.g. nondet). + if let ResolvedKind::Custom { hash } = &resolved.kind { + if !available_custom.contains(hash) { + return Err(make_malformed_runner_error(&format!( + "custom runner {} is not registered in this execution scope", + resolved.id + ))); + } + } get_arch(supervisor, limiter, resolved).await } @@ -323,9 +336,10 @@ pub(crate) async fn map_runner_file( contract_address: calldata::Address, state: public_abi::StorageType, code_slot: crate::SlotID, - runner: symbol_table::GlobalSymbol, + runner: &str, path_in_runner: &str, path_in_vfs: &str, + available_custom: &rpds::HashTrieSet, ) -> anyhow::Result<()> { let (_id, arch) = load_runner( supervisor, @@ -334,13 +348,14 @@ pub(crate) async fn map_runner_file( code_slot, limiter, runner, + available_custom, ) .await?; map_archive_file(preview1, limiter, &arch, path_in_runner, path_in_vfs) } impl Ctx<'_, '_> { - fn resolve_runner(&self, id: symbol_table::GlobalSymbol) -> anyhow::Result { + fn resolve_runner(&self, id: &str) -> anyhow::Result { resolve_runner( self.supervisor, self.contract_address, @@ -573,7 +588,7 @@ impl Ctx<'_, '_> { runner: uid, action, } => { - let resolved = self.resolve_runner(*uid)?; + let resolved = self.resolve_runner(uid)?; let (uid, new_arch) = self.get_arch(resolved).await?; Box::pin(self.apply(action, uid, &new_arch)) @@ -581,7 +596,7 @@ impl Ctx<'_, '_> { .with_context(|| format!("With {uid}")) } InitAction::Depends(uid) => { - let resolved = self.resolve_runner(*uid)?; + let resolved = self.resolve_runner(uid)?; if !self.visited.insert(resolved.id) { return Ok(None); diff --git a/executor/src/wasi/genlayer_sdk.rs b/executor/src/wasi/genlayer_sdk.rs index 2d6c99830..265c76b21 100644 --- a/executor/src/wasi/genlayer_sdk.rs +++ b/executor/src/wasi/genlayer_sdk.rs @@ -248,6 +248,10 @@ pub struct VMDataAccumulator { pub messages_value_decremented: primitive_types::U256, pub emissions: Vec, pub message_fee_allocation: Vec, + /// Custom runner hashes registered in (and inherited into) this execution + /// scope. Only these may be resolved via `custom:`. A nondet sub-VM + /// starts empty, so it cannot see runners the deterministic scope registered. + pub custom_runners: rpds::HashTrieSet, } impl VMDataAccumulator { @@ -778,6 +782,9 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { .messages_value_decremented, emissions: Vec::new(), message_fee_allocation: Vec::new(), + // CallContract is a deterministic sub-call: inherit the + // runners registered so far. + custom_runners: self.context.data.accumulator.custom_runners.clone(), }, det_subvm_hashes: Default::default(), }); @@ -1602,10 +1609,16 @@ impl ContextVFS<'_> { let is_det = self.context.data.conf.is_deterministic; let supervisor = self.context.data.supervisor.clone(); + let hash = crate::runners::custom_runner_hash(&code); let id = supervisor .register_custom_runner(code, supervisor.limiter.get(is_det)) .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?; + // Scope the runner to this execution (and its deterministic children) so + // it cannot be resolved from an unrelated scope (e.g. a nondet sub-VM). + self.context.data.accumulator.custom_runners = + self.context.data.accumulator.custom_runners.insert(hash); + let data = calldata::encode(&calldata::Value::Str(id.as_str().to_owned())); self.place_content(vfs::FileContents::from(bytes::Bytes::from(data))) } @@ -1629,6 +1642,7 @@ impl ContextVFS<'_> { let contract_address = self.context.data.message_data.message.contract_address; let state = self.context.data.conf.state_mode; let code_slot = self.context.data.conf.code_slot; + let available_custom = self.context.data.accumulator.custom_runners.clone(); rt::supervisor::actions::map_runner_file( &supervisor, @@ -1637,9 +1651,10 @@ impl ContextVFS<'_> { contract_address, state, code_slot, - symbol_table::GlobalSymbol::from(runner), + &runner, &path_in_runner, &path_in_vfs, + &available_custom, ) .await .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?; @@ -1798,6 +1813,9 @@ impl ContextVFS<'_> { .messages_value_decremented, emissions: Vec::new(), message_fee_allocation: Vec::new(), + // Nondet is an isolated execution scope: it must NOT see custom + // runners registered by the deterministic scope. + custom_runners: Default::default(), }; let vm_data = Box::new(SingleVMData { @@ -1886,6 +1904,8 @@ impl ContextVFS<'_> { messages_value_decremented: primitive_types::U256::max_value(), emissions: Vec::new(), message_fee_allocation: Vec::new(), + // Sandbox is a deterministic sub-VM: inherit the registered runners. + custom_runners: self.context.data.accumulator.custom_runners.clone(), }; std::mem::swap(&mut self.context.data.accumulator, &mut fake_my_data); diff --git a/tests/cases/stable/runners/nondet_custom_runner.0.stdout b/tests/cases/stable/runners/nondet_custom_runner.0.stdout index 1ad6a7116..3a6b81bc5 100644 --- a/tests/cases/stable/runners/nondet_custom_runner.0.stdout +++ b/tests/cases/stable/runners/nondet_custom_runner.0.stdout @@ -1,2 +1 @@ -nondet mapped det-registered runner (LEAK) -executed with `Return(null)` +executed with `VMError("invalid_contract malformed_runner")` diff --git a/tests/cases/stable/runners/nondet_custom_runner.py b/tests/cases/stable/runners/nondet_custom_runner.py index a10e87617..6fe7ad73b 100644 --- a/tests/cases/stable/runners/nondet_custom_runner.py +++ b/tests/cases/stable/runners/nondet_custom_runner.py @@ -14,7 +14,7 @@ def leader(): # runner from inside nondet. Custom runners should be scoped to the # execution that registered them, so this map MUST fail — but with a # shared registry it may leak. - for _ in range(10**6): + for _ in range(10**4): pass try: map_file(rid, 'file', '/mapped.txt') From 27dc6c7d03d9b25f21f3e6190516431a7d713c87 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 18:06:04 +0900 Subject: [PATCH 085/124] =?UTF-8?q?fix(executor):=20keep=20runner.json=20D?= =?UTF-8?q?epends/With=20ids=20as=20String=20until=20validated=20?= =?UTF-8?q?=F0=9F=94=92=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/src/runners/actions.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/executor/src/runners/actions.rs b/executor/src/runners/actions.rs index ceef35ea1..6065397f9 100644 --- a/executor/src/runners/actions.rs +++ b/executor/src/runners/actions.rs @@ -19,9 +19,7 @@ pub enum InitAction { val: String, }, SetArgs(Vec), - Depends( - #[serde(deserialize_with = "util::global_symbol_deserialize")] symbol_table::GlobalSymbol, - ), + Depends(String), LinkWasm(Arc), StartWasm(Arc), @@ -32,8 +30,7 @@ pub enum InitAction { Seq(Vec), With { - #[serde(deserialize_with = "util::global_symbol_deserialize")] - runner: symbol_table::GlobalSymbol, + runner: String, action: Box, }, } From c2136c18579c69f03f398feeb264a31d5dabe60a Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 18:16:43 +0900 Subject: [PATCH 086/124] =?UTF-8?q?fix(scripting):=20set=20per-state=20pac?= =?UTF-8?q?kage.path/cpath=20instead=20of=20process-global=20LUA=5FPATH=20?= =?UTF-8?q?=F0=9F=94=92=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/implementation/src/scripting/mod.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/modules/implementation/src/scripting/mod.rs b/modules/implementation/src/scripting/mod.rs index 623cb4e4d..4bbaabb00 100644 --- a/modules/implementation/src/scripting/mod.rs +++ b/modules/implementation/src/scripting/mod.rs @@ -156,9 +156,6 @@ impl UserVM { { use mlua::StdLib; - std::env::set_var("LUA_PATH", &mod_config.lua_path); - std::env::set_var("LUA_CPATH", mod_config.lua_path.replace(".lua", ".so")); - let lua_libs = StdLib::COROUTINE | StdLib::TABLE | StdLib::IO @@ -170,6 +167,15 @@ impl UserVM { vm.load_std_libs(lua_libs).context("loading stdlib")?; + // Set the module search paths on this Lua state directly. Lua 5.3's + // `require` reads `package.path`/`package.cpath` (there is no in-Lua + // `LUA_PATH` global as in Lua 5.0). Doing it per-state avoids mutating + // the process-global LUA_PATH/LUA_CPATH env vars, which raced across the + // Web and LLM VM pools initializing concurrently in the same process. + let package: mlua::Table = vm.globals().get("package")?; + package.set("path", mod_config.lua_path.as_str())?; + package.set("cpath", mod_config.lua_path.replace(".lua", ".so"))?; + preload_lsqlite3(&vm).context("preloading lsqlite3")?; vm.globals().set( From 1b87cd6180a08a700c555c6236f931e64d2c6a2d Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 18:19:35 +0900 Subject: [PATCH 087/124] =?UTF-8?q?fix(executor):=20validate=20method=5Fho?= =?UTF-8?q?sts=20indices=20up=20front=20to=20avoid=20panic=20=F0=9F=94=92?= =?UTF-8?q?=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/src/exe/run.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/executor/src/exe/run.rs b/executor/src/exe/run.rs index 7510de24d..18c3673d8 100644 --- a/executor/src/exe/run.rs +++ b/executor/src/exe/run.rs @@ -168,6 +168,16 @@ pub fn handle(args: Args, mut config: config::Config) -> Result<()> { let method_hosts = execution_data.method_hosts.clone(); + // Validate every method->host mapping up front, once, so all later host + // selection (here and inside the VM) can index `hosts` safely instead of + // panicking on a misconfigured index. + if let Some(&bad) = method_hosts.iter().find(|&&h| h as usize >= hosts.len()) { + anyhow::bail!( + "method_hosts references host index {bad} but only {} host(s) are configured", + hosts.len() + ); + } + // Charge the per-bucket up-front fees now that the hosts are connected. If a // bucket cannot cover its `subtract_on_start`, report the resulting VM error // to the host as a normal receipt instead of crashing during setup. From de1b7d3e66a71898961f406d908bc16f2819258a Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 18:19:36 +0900 Subject: [PATCH 088/124] =?UTF-8?q?fix(manager):=20cap=20max=5Fexecution?= =?UTF-8?q?=5Fminutes=20at=2024h=20(avoid=20i64=20overflow)=20=F0=9F=90=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/implementation/src/manager/run.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/implementation/src/manager/run.rs b/modules/implementation/src/manager/run.rs index 3bbce557e..658eb10bd 100644 --- a/modules/implementation/src/manager/run.rs +++ b/modules/implementation/src/manager/run.rs @@ -1067,8 +1067,9 @@ pub async fn start_genvm( id: genvm_id, process_handle: tokio::sync::Mutex::new(child), started_at: chrono::Utc::now(), + // Cap at 24h so a huge value can't overflow the i64 cast / Duration. strict_deadline: chrono::Utc::now() - + chrono::Duration::minutes(req.max_execution_minutes as i64), + + chrono::Duration::minutes(req.max_execution_minutes.min(24 * 60) as i64), stdout_stderr_sem, stdout: tokio::sync::OnceCell::new(), From f3481b7bfa01539d282f5ad0bf712f8cb1ccee73 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 18:37:14 +0900 Subject: [PATCH 089/124] =?UTF-8?q?refactor(modules):=20drop=20get=5Fstats?= =?UTF-8?q?=20RPC;=20manager=20collects=20metrics=20directly=20=E2=99=BB?= =?UTF-8?q?=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The manager already gathers per-execution llm/web metrics from its own execution context (collect_metrics), so the executor->module GetStats round-trip was redundant. Remove the GetStats message variants, the single-variant FullResponse wrappers, and Module::get_stats. --- executor/src/lib.rs | 53 ++--------------------- executor/src/modules.rs | 20 --------- modules/implementation/src/llm/handler.rs | 47 +++++--------------- modules/implementation/src/web/handler.rs | 38 +++------------- modules/interfaces/src/lib.rs | 3 -- 5 files changed, 22 insertions(+), 139 deletions(-) diff --git a/executor/src/lib.rs b/executor/src/lib.rs index 5b0877d53..3d5050fcf 100644 --- a/executor/src/lib.rs +++ b/executor/src/lib.rs @@ -274,56 +274,11 @@ pub async fn run_with( .context("notify non-deterministic disagreement")?; } - log_debug!("all executions done, collecting stats"); - - let web_metrics = supervisor - .modules - .web - .get_stats(genvm_modules_interfaces::web::Message::GetStats) - .await - .ok(); - let llm_metrics = supervisor - .modules - .llm - .get_stats(genvm_modules_interfaces::llm::Message::GetStats) - .await - .ok(); - - #[derive(serde::Serialize)] - struct AllMetrics<'a> { - web: Option, - llm: Option, - gvm: &'a crate::Metrics, - } - - impl calldata::codec::Encode for AllMetrics<'_> { - type Error = W::Error; - - fn encode(&self, enc: &mut calldata::Encoder) -> Result<(), Self::Error> { - enc.start_map(3)?; - - enc.push_map_k("gvm")?; - calldata::codec::Encode::encode(self.gvm, enc)?; - - enc.push_map_k("llm")?; - calldata::codec::Encode::encode(&self.llm, enc)?; - - enc.push_map_k("web")?; - calldata::codec::Encode::encode(&self.web, enc)?; - - Ok(()) - } - } - - let all_metrics = AllMetrics { - web: web_metrics, - llm: llm_metrics, - gvm: &supervisor.shared_data.metrics, - }; - - let all_metrics = calldata::to_value(&all_metrics); + // Module (llm/web) metrics are collected by the manager from its own + // execution context; the executor only reports its own counters here. + let gvm_metrics = calldata::to_value(&supervisor.shared_data.metrics); - log_info!(metrics:serde = all_metrics; "metrics"); + log_info!(metrics:serde = gvm_metrics; "metrics"); log_debug!("sending final result"); diff --git a/executor/src/modules.rs b/executor/src/modules.rs index 91acfe726..e6d5dffc4 100644 --- a/executor/src/modules.rs +++ b/executor/src/modules.rs @@ -194,26 +194,6 @@ impl Module { } } - pub async fn get_stats(&self, val: V) -> anyhow::Result - where - V: calldata::codec::Encode, Error = std::convert::Infallible>, - { - let zelf = self.imp.lock().await; - let mut zelf = sync::Lock::new(zelf, self.metrics.gep(|x| &x.time)); - - match &mut zelf.stream { - None => Ok(calldata::Value::Null), - Some(stream) => { - write_message(stream, &calldata::encode_obj(&val)).await?; - let response = read_message(stream).await?; - - let response = calldata::decode(&response)?; - - Ok(response) - } - } - } - pub async fn send(&self, val: V) -> anyhow::Result> where V: calldata::codec::Encode, Error = std::convert::Infallible>, diff --git a/modules/implementation/src/llm/handler.rs b/modules/implementation/src/llm/handler.rs index 8e5bdb44e..e221e8073 100644 --- a/modules/implementation/src/llm/handler.rs +++ b/modules/implementation/src/llm/handler.rs @@ -15,7 +15,6 @@ pub struct Inner { _ctx: sync::DArc, ctx_val: mlua::Value, - metrics: sync::DArc, genvm_id: genvm_modules_interfaces::GenVMId, } @@ -27,25 +26,9 @@ pub struct Provider { pub providers: Arc>>, } -#[derive(serde::Serialize)] -#[serde(untagged)] -pub enum FullResponse { - Answer(llm_iface::PromptAnswer), - GetStats(calldata::Value), -} - -impl calldata::codec::Encode for FullResponse { - type Error = W::Error; - - fn encode(&self, enc: &mut calldata::Encoder) -> std::result::Result<(), Self::Error> { - match self { - FullResponse::Answer(v) => calldata::codec::Encode::encode(v, enc), - FullResponse::GetStats(v) => calldata::codec::Encode::encode(v, enc), - } - } -} - -impl MessageHandlerProvider for Provider { +impl MessageHandlerProvider + for Provider +{ type Ctx = LlmSubContext; fn create_execution_context( @@ -70,8 +53,9 @@ impl MessageHandlerProvider, - ) -> anyhow::Result> - { + ) -> anyhow::Result< + impl MessageHandler, + > { let genvm_id = ctx.scripting.hello.genvm_id; let user_vm = self.vm_pool.get(); @@ -85,7 +69,6 @@ impl MessageHandlerProvider); -impl crate::common::MessageHandler for Handler { +impl crate::common::MessageHandler for Handler { async fn handle( &self, message: llm_iface::Message, - ) -> crate::common::ModuleResult { + ) -> crate::common::ModuleResult { match message { llm_iface::Message::Prompt { payload, @@ -138,20 +121,14 @@ impl crate::common::MessageHandler for Handler self.0 .exec_prompt(self.0.clone(), payload, remaining_fuel_as_gen) .await - .map(FullResponse::Answer) } llm_iface::Message::PromptTemplate { payload, remaining_fuel_as_gen, - } => self - .0 - .exec_prompt_template(self.0.clone(), payload, remaining_fuel_as_gen) - .await - .map(FullResponse::Answer), - - llm_iface::Message::GetStats => { - let res = calldata::to_value(&self.0.metrics); - Ok(FullResponse::GetStats(res)) + } => { + self.0 + .exec_prompt_template(self.0.clone(), payload, remaining_fuel_as_gen) + .await } } } diff --git a/modules/implementation/src/web/handler.rs b/modules/implementation/src/web/handler.rs index 4228474d2..d0d7892f4 100644 --- a/modules/implementation/src/web/handler.rs +++ b/modules/implementation/src/web/handler.rs @@ -17,14 +17,12 @@ pub struct Inner { ctx_val: mlua::Value, max_wait_after_loaded: std::time::Duration, - - metrics: sync::DArc, } struct Handler(Arc); -impl common::MessageHandler for Handler { - async fn handle(&self, message: web_iface::Message) -> common::ModuleResult { +impl common::MessageHandler for Handler { + async fn handle(&self, message: web_iface::Message) -> common::ModuleResult { match message { web_iface::Message::Request(payload, size_limit) => { let vm = &self.0.user_vm.vm; @@ -45,7 +43,7 @@ impl common::MessageHandler for Handler { let res = self.0.user_vm.vm.from_value(res)?; - Ok(FullResponse::Answer(RenderAnswer::Response(res))) + Ok(RenderAnswer::Response(res)) } web_iface::Message::Render(payload, size_limit) => { let vm = &self.0.user_vm.vm; @@ -81,12 +79,7 @@ impl common::MessageHandler for Handler { let res = self.0.user_vm.vm.from_value(res)?; - Ok(FullResponse::Answer(res)) - } - - web_iface::Message::GetStats => { - let res = calldata::to_value(&self.0.metrics); - Ok(FullResponse::GetStats(res)) + Ok(res) } } } @@ -96,30 +89,12 @@ impl common::MessageHandler for Handler { } } -#[derive(serde::Serialize)] -#[serde(untagged)] -pub enum FullResponse { - Answer(web_iface::RenderAnswer), - GetStats(calldata::Value), -} - -impl calldata::codec::Encode for FullResponse { - type Error = W::Error; - - fn encode(&self, enc: &mut calldata::Encoder) -> std::result::Result<(), Self::Error> { - match self { - FullResponse::Answer(v) => calldata::codec::Encode::encode(v, enc), - FullResponse::GetStats(v) => calldata::codec::Encode::encode(v, enc), - } - } -} - pub struct HandlerProvider { pub vm_pool: scripting::pool::Pool, WebSubContext>, pub config: sync::DArc, } -impl common::MessageHandlerProvider +impl common::MessageHandlerProvider for HandlerProvider { type Ctx = WebSubContext; @@ -143,7 +118,7 @@ impl common::MessageHandlerProvider, ) -> anyhow::Result< - impl common::MessageHandler, + impl common::MessageHandler, > { let user_vm = self.vm_pool.get(); @@ -154,7 +129,6 @@ impl common::MessageHandlerProvider Date: Tue, 23 Jun 2026 18:44:31 +0900 Subject: [PATCH 090/124] =?UTF-8?q?fix(scripting):=20check=20out=20lua=20V?= =?UTF-8?q?Ms=20exclusively=20from=20the=20pool=20=F0=9F=94=92=EF=B8=8F?= =?UTF-8?q?=F0=9F=90=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pool::get picked a random VM and cloned its Arc, so two concurrent executions could drive the same lua_State at once and corrupt shared interpreter state. Replace it with an atomic checkout (semaphore + free queue) that hands out a VM exclusively and returns it on guard drop. Closes GVM-291 --- modules/implementation/src/llm/handler.rs | 8 +- modules/implementation/src/scripting/pool.rs | 86 +++++++++++++++++--- modules/implementation/src/web/handler.rs | 6 +- 3 files changed, 81 insertions(+), 19 deletions(-) diff --git a/modules/implementation/src/llm/handler.rs b/modules/implementation/src/llm/handler.rs index e221e8073..3cf18ceaa 100644 --- a/modules/implementation/src/llm/handler.rs +++ b/modules/implementation/src/llm/handler.rs @@ -1,4 +1,4 @@ -use super::{ctx, prompt, scripting, UserVM}; +use super::{ctx, prompt, scripting}; use crate::common::{MessageHandler, MessageHandlerProvider, ModuleError, ModuleResult}; use anyhow::Context as _; use genvm_common::*; @@ -9,8 +9,10 @@ use mlua::LuaSerdeExt; use std::{collections::BTreeMap, sync::Arc}; +type VmGuard = scripting::pool::PoolGuard, LlmSubContext>; + pub struct Inner { - user_vm: Arc, + user_vm: VmGuard, _ctx: sync::DArc, ctx_val: mlua::Value, @@ -57,7 +59,7 @@ impl MessageHandlerProvider, > { let genvm_id = ctx.scripting.hello.genvm_id; - let user_vm = self.vm_pool.get(); + let user_vm = self.vm_pool.get().await; let (handler_ctx, ctx_val) = user_vm.create_ctx(&ctx)?; diff --git a/modules/implementation/src/scripting/pool.rs b/modules/implementation/src/scripting/pool.rs index 0ce3ea006..8d54b40f2 100644 --- a/modules/implementation/src/scripting/pool.rs +++ b/modules/implementation/src/scripting/pool.rs @@ -1,19 +1,76 @@ use std::sync::Arc; struct Inner { - vms: Vec>>, + free: crossbeam::queue::ArrayQueue>>, } -#[derive(Clone)] -pub struct Pool(Arc>); +/// A fixed-size pool of Lua VMs. A VM is checked out exclusively via [`Pool::get`] +/// and returned to the pool when the [`PoolGuard`] is dropped, so a single +/// `lua_State` is never driven by two executions concurrently. +pub struct Pool { + inner: Arc>, + // `available` counts the VMs currently in `free`; acquiring a permit + // guarantees a subsequent `pop` succeeds. + available: Arc, +} -impl Pool { - pub fn get(&self) -> Arc> { - let mut key: [u8; 1] = [0; 1]; +impl Clone for Pool { + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + available: self.available.clone(), + } + } +} + +/// Exclusive checkout of one VM. Dereferences to the underlying [`super::UserVM`] +/// and returns it to the pool on drop. +pub struct PoolGuard { + vm: Option>>, + inner: Arc>, + // Released only after the VM has been returned to `free` (see `Drop`). + _permit: tokio::sync::OwnedSemaphorePermit, +} + +impl std::ops::Deref for PoolGuard { + type Target = super::UserVM; - rand::fill(&mut key); + fn deref(&self) -> &Self::Target { + self.vm + .as_ref() + .expect("vm is present until the guard is dropped") + } +} - self.0.vms[key[0] as usize % self.0.vms.len()].clone() +impl Drop for PoolGuard { + fn drop(&mut self) { + if let Some(vm) = self.vm.take() { + // Return the VM before `_permit` is released so the next waiter that + // wakes on the freed permit is guaranteed to find a VM in `free`. + let _ = self.inner.free.push(vm); + } + } +} + +impl Pool { + /// Atomically checks out a VM, waiting if all VMs are currently in use. + pub async fn get(&self) -> PoolGuard { + let permit = self + .available + .clone() + .acquire_owned() + .await + .expect("vm pool semaphore is never closed"); + let vm = self + .inner + .free + .pop() + .expect("holding a permit guarantees a free vm"); + PoolGuard { + vm: Some(vm), + inner: self.inner.clone(), + _permit: permit, + } } } @@ -27,12 +84,15 @@ where if cnt == 0 { anyhow::bail!("vm pool size must be >= 1"); } - let mut vms = Vec::new(); + let free = crossbeam::queue::ArrayQueue::new(cnt); for _i in 0..cnt { - vms.push(Arc::new(vm_supplier().await?)); + free.push(Arc::new(vm_supplier().await?)) + .ok() + .expect("queue capacity matches the number of VMs"); } - let inner = Inner { vms }; - - Ok(Pool(Arc::new(inner))) + Ok(Pool { + inner: Arc::new(Inner { free }), + available: Arc::new(tokio::sync::Semaphore::new(cnt)), + }) } diff --git a/modules/implementation/src/web/handler.rs b/modules/implementation/src/web/handler.rs index d0d7892f4..c1a99931c 100644 --- a/modules/implementation/src/web/handler.rs +++ b/modules/implementation/src/web/handler.rs @@ -8,10 +8,10 @@ use mlua::LuaSerdeExt; use std::sync::Arc; type WebSubContext = crate::manager::execution_context::WebSubContext; -type UserVM = scripting::UserVM, WebSubContext>; +type VmGuard = scripting::pool::PoolGuard, WebSubContext>; pub struct Inner { - user_vm: Arc, + user_vm: VmGuard, _ctx: Arc, ctx_val: mlua::Value, @@ -120,7 +120,7 @@ impl common::MessageHandlerProvider anyhow::Result< impl common::MessageHandler, > { - let user_vm = self.vm_pool.get(); + let user_vm = self.vm_pool.get().await; let (handler_ctx, ctx_val) = user_vm.create_ctx(&ctx)?; From fa35b6d64e0360f72a4f103a16e2716f26f1b82c Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 18:48:09 +0900 Subject: [PATCH 091/124] =?UTF-8?q?fix(manager):=20gate=20version=20patch-?= =?UTF-8?q?walk=20by=20available=5Fafter=20=F0=9F=94=92=EF=B8=8F?= =?UTF-8?q?=F0=9F=90=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The patch-walk adopted any contiguous higher patch present in the manifest without re-checking its available_after, so a staged future or rc patch could activate before its time gate opened — during a rolling update with inconsistent manifests this diverges consensus. Only adopt the next patch once its gate has opened. --- modules/implementation/src/manager/versioning.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/modules/implementation/src/manager/versioning.rs b/modules/implementation/src/manager/versioning.rs index dc9346fb8..eea48fd5e 100644 --- a/modules/implementation/src/manager/versioning.rs +++ b/modules/implementation/src/manager/versioning.rs @@ -146,13 +146,18 @@ impl Ctx { .map(|(ver, _)| *ver) .max()?; + // Walk forward to the newest contiguous patch, but only adopt a patch + // whose time gate has already opened. Skipping `available_after` here + // would activate a future (or rc) patch prematurely, which during a + // rolling update with staged manifests causes consensus divergence. loop { let mut next = ver; next.patch += 1; - if lock.executor_versions.contains_key(&next) { - ver = next; - } else { - break; + match lock.executor_versions.get(&next) { + Some(ev) if ev.available_after <= timestamp => { + ver = next; + } + _ => break, } } From e20389b06caa600513b80f8e537ba044d7600572 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 18:48:22 +0900 Subject: [PATCH 092/124] =?UTF-8?q?fix(llm):=20saturate=20provider-reporte?= =?UTF-8?q?d=20token=20counts=20instead=20of=20wrapping=20=F0=9F=94=92?= =?UTF-8?q?=EF=B8=8F=F0=9F=90=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Provider token usage was narrowed u64->u32 with `as` and summed with unchecked u32 addition. A misreporting or compromised provider could overflow these to a tiny total (under-billing when per-token pricing is on) or panic a debug build. Narrow via try_from with saturation + error log, and sum with saturating_add. --- modules/implementation/src/llm/providers.rs | 49 +++++++++++++-------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/modules/implementation/src/llm/providers.rs b/modules/implementation/src/llm/providers.rs index ef560bb3d..a6d2eb9b2 100644 --- a/modules/implementation/src/llm/providers.rs +++ b/modules/implementation/src/llm/providers.rs @@ -54,7 +54,7 @@ impl TokenUsage { Self { input: Some(input), output: Some(output), - total: Some(input + output), + total: Some(input.saturating_add(output)), ..Default::default() } } @@ -74,7 +74,7 @@ impl TokenUsage { } let input = self.input.unwrap_or_default(); let output = self.output.unwrap_or_default(); - if total < input + output { + if total < input.saturating_add(output) { return Err(TokensSanityError::TotalLessThanParts { total, input, @@ -85,6 +85,17 @@ impl TokenUsage { } } +/// Narrows a provider-reported token count (a `u64` from response JSON) to +/// `u32`, saturating instead of wrapping. A value that does not fit `u32` is not +/// plausible real usage and most likely a misreporting or compromised provider; +/// clamping and logging avoids the silent wrap that could otherwise under-bill. +fn narrow_token_count(v: u64) -> u32 { + u32::try_from(v).unwrap_or_else(|_| { + log_error!(value = v; "provider reported token count exceeding u32; saturating to u32::MAX"); + u32::MAX + }) +} + #[derive(Debug, Clone)] pub struct ProviderResponse { pub result: T, @@ -254,23 +265,23 @@ fn extract_openai_tokens(body: &serde_json::Value) -> TokenUsage { let input = usage .and_then(|v| v.get("prompt_tokens")) .and_then(|v| v.as_u64()) - .map(|v| v as u32); + .map(narrow_token_count); let output = usage .and_then(|v| v.get("completion_tokens")) .and_then(|v| v.as_u64()) - .map(|v| v as u32); + .map(narrow_token_count); let total = usage .and_then(|v| v.get("total_tokens")) .and_then(|v| v.as_u64()) - .map(|v| v as u32); + .map(narrow_token_count); let cache_read_tokens = usage .and_then(|v| v.pointer("/prompt_tokens_details/cached_tokens")) .and_then(|v| v.as_u64()) - .map(|v| v as u32); + .map(narrow_token_count); let cache_write_tokens = usage .and_then(|v| v.pointer("/prompt_tokens_details/cache_write_tokens")) .and_then(|v| v.as_u64()) - .map(|v| v as u32); + .map(narrow_token_count); TokenUsage { input, output, @@ -479,13 +490,13 @@ fn extract_ollama_tokens(body: &serde_json::Value) -> TokenUsage { let input = body .get("prompt_eval_count") .and_then(|v| v.as_u64()) - .map(|v| v as u32); + .map(narrow_token_count); let output = body .get("eval_count") .and_then(|v| v.as_u64()) - .map(|v| v as u32); + .map(narrow_token_count); let total = match (input, output) { - (Some(i), Some(o)) => Some(i + o), + (Some(i), Some(o)) => Some(i.saturating_add(o)), _ => None, }; let mut raw = serde_json::Map::new(); @@ -605,19 +616,19 @@ fn extract_gemini_tokens(body: &serde_json::Value) -> TokenUsage { let input = usage .and_then(|v| v.get("promptTokenCount")) .and_then(|v| v.as_u64()) - .map(|v| v as u32); + .map(narrow_token_count); let output = usage .and_then(|v| v.get("candidatesTokenCount")) .and_then(|v| v.as_u64()) - .map(|v| v as u32); + .map(narrow_token_count); let total = usage .and_then(|v| v.get("totalTokenCount")) .and_then(|v| v.as_u64()) - .map(|v| v as u32); + .map(narrow_token_count); let cache_read_tokens = usage .and_then(|v| v.get("cachedContentTokenCount")) .and_then(|v| v.as_u64()) - .map(|v| v as u32); + .map(narrow_token_count); TokenUsage { input, output, @@ -796,23 +807,23 @@ fn extract_anthropic_tokens(body: &serde_json::Value) -> TokenUsage { let input = usage .and_then(|v| v.get("input_tokens")) .and_then(|v| v.as_u64()) - .map(|v| v as u32); + .map(narrow_token_count); let output = usage .and_then(|v| v.get("output_tokens")) .and_then(|v| v.as_u64()) - .map(|v| v as u32); + .map(narrow_token_count); let total = match (input, output) { - (Some(i), Some(o)) => Some(i + o), + (Some(i), Some(o)) => Some(i.saturating_add(o)), _ => None, }; let cache_read_tokens = usage .and_then(|v| v.get("cache_read_input_tokens")) .and_then(|v| v.as_u64()) - .map(|v| v as u32); + .map(narrow_token_count); let cache_write_tokens = usage .and_then(|v| v.get("cache_creation_input_tokens")) .and_then(|v| v.as_u64()) - .map(|v| v as u32); + .map(narrow_token_count); TokenUsage { input, output, From bbaa87ace6fb98bec71b8acf6c88621feff164ff Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 18:48:29 +0900 Subject: [PATCH 093/124] =?UTF-8?q?fix(webdriver):=20isolate=20each=20rend?= =?UTF-8?q?er=20in=20its=20own=20browser=20context=20=F0=9F=94=92=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Renders shared the default BrowserContext, so cookies, localStorage, IndexedDB, service workers and HSTS persisted across requests and leaked between tenants on a node. Open each render in a fresh createBrowserContext() and tear it down alongside the page. --- modules/webdriver/src/prj/src/index.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/modules/webdriver/src/prj/src/index.ts b/modules/webdriver/src/prj/src/index.ts index 37ce5b818..f5fa0cd5f 100644 --- a/modules/webdriver/src/prj/src/index.ts +++ b/modules/webdriver/src/prj/src/index.ts @@ -240,7 +240,11 @@ async function renderPageWithBrowser( maxPageHeapMB = DEFAULT_MAX_PAGE_HEAP_MB, } = options; - const page = await browserInstance.newPage(); + // Each render runs in its own browser context so cookies, localStorage, + // IndexedDB, service workers and HSTS state never leak between tenants + // sharing this long-lived browser. + const context = await browserInstance.createBrowserContext(); + const page = await context.newPage(); try { await ssrf.installSsrfGuard(page); @@ -301,7 +305,9 @@ async function renderPageWithBrowser( } throw e; } finally { - await page.close(); + // Close the page and its context together; the context teardown is what + // actually discards the per-request browsing state. + await Promise.allSettled([page.close(), context.close()]); } } From fd4ee9ff8a2fbe64d53e9a808ec5d1b3a8a0af02 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 19:11:36 +0900 Subject: [PATCH 094/124] =?UTF-8?q?fix(executor):=20reject=20misleading=20?= =?UTF-8?q?wss://=20module=20scheme=20=F0=9F=94=92=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wss:// implies TLS, but the connector only speaks the plaintext length-prefixed protocol and silently downgraded to a raw TCP link an operator could believe was encrypted. Reject wss:// with guidance to terminate TLS in a proxy; ws:// stays as an explicit plaintext alias. --- executor/src/modules.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/executor/src/modules.rs b/executor/src/modules.rs index e6d5dffc4..aaff5db6d 100644 --- a/executor/src/modules.rs +++ b/executor/src/modules.rs @@ -59,10 +59,21 @@ const FD_PREFIX: &str = "fd://"; /// Connect to a module endpoint /// Supports: -/// - TCP: "host:port" or "ws://host:port" or "wss://host:port" +/// - TCP: "host:port" or "ws://host:port" (the latter is a plaintext alias) /// - Unix socket: "unix:///path/to/socket" /// - File descriptor: "fd://fd" (for bidirectional fd like socketpair) async fn connect(url: &str) -> anyhow::Result { + // `wss://` implies TLS, but this connector only speaks the plaintext + // length-prefixed protocol. Reject it rather than silently downgrading to + // an unencrypted link an operator believes is secure. Terminate TLS in a + // proxy and point the executor at the proxy's plain `host:port` instead. + if url.starts_with("wss://") { + anyhow::bail!( + "module scheme 'wss://' is not supported (no TLS is performed); \ + use 'host:port', 'ws://host:port', 'unix://', or 'fd://', and \ + terminate TLS in a proxy" + ); + } if let Some(socket_path) = url.strip_prefix(UNIX_PREFIX) { let stream = tokio::net::UnixStream::connect(socket_path) .await @@ -76,11 +87,8 @@ async fn connect(url: &str) -> anyhow::Result { let stream = unsafe { genvm_common::io::AsyncCustomFD::from_raw_fd(fd)? }; Ok(Box::new(stream)) } else { - // Strip ws:// or wss:// prefix if present for TCP connection - let addr = url - .strip_prefix("ws://") - .or_else(|| url.strip_prefix("wss://")) - .unwrap_or(url); + // `ws://` is a plaintext alias for a raw TCP connection. + let addr = url.strip_prefix("ws://").unwrap_or(url); let stream = tokio::net::TcpStream::connect(addr) .await From c3338a6942042d04a33431efc5781af7aefa8203 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 19:30:14 +0900 Subject: [PATCH 095/124] =?UTF-8?q?chore(abi):=20remove=20json2=20output?= =?UTF-8?q?=20format=20alias=20=F0=9F=94=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit json and json2 were identical; collapse to a single json variant. --- executor/crates/sdk-rs/src/abi/gl_call.rs | 5 ----- modules/implementation/src/llm/handler.rs | 6 +----- runners/genlayer-py-std/src/genlayer/nondet/__init__.py | 5 +---- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/executor/crates/sdk-rs/src/abi/gl_call.rs b/executor/crates/sdk-rs/src/abi/gl_call.rs index 41b7d8938..c7b69fc97 100644 --- a/executor/crates/sdk-rs/src/abi/gl_call.rs +++ b/executor/crates/sdk-rs/src/abi/gl_call.rs @@ -231,14 +231,9 @@ pub mod llm_iface { #[serde(rename = "text")] #[calldata(rename = "text")] Text, - // `json` and `json2` are accepted aliases with identical behavior: the raw - // model text is returned as-is and the contract parses it. #[serde(rename = "json")] #[calldata(rename = "json")] JSON, - #[serde(rename = "json2")] - #[calldata(rename = "json2")] - JSON2, } fn default_text() -> OutputFormat { diff --git a/modules/implementation/src/llm/handler.rs b/modules/implementation/src/llm/handler.rs index 3cf18ceaa..2cf78d303 100644 --- a/modules/implementation/src/llm/handler.rs +++ b/modules/implementation/src/llm/handler.rs @@ -209,15 +209,11 @@ impl Inner { async fn exec_prompt( &self, _zelf: Arc, - mut payload: llm_iface::PromptPayload, + payload: llm_iface::PromptPayload, remaining_fuel_as_gen: primitive_types::U256, ) -> ModuleResult { log_debug_into!(&LoggerWithId, payload:serde = payload, genvm_id:id = self.genvm_id.0; "exec_prompt start"); - if payload.response_format == genvm_modules_interfaces::llm::OutputFormat::JSON2 { - payload.response_format = genvm_modules_interfaces::llm::OutputFormat::JSON; - } - let payload = self .user_vm .vm diff --git a/runners/genlayer-py-std/src/genlayer/nondet/__init__.py b/runners/genlayer-py-std/src/genlayer/nondet/__init__.py index ca964cb7d..4c4981701 100644 --- a/runners/genlayer-py-std/src/genlayer/nondet/__init__.py +++ b/runners/genlayer-py-std/src/genlayer/nondet/__init__.py @@ -125,9 +125,6 @@ def exec_prompt( format = config.get('response_format', 'text') - if format == 'json': - format = 'json2' - return gl_call.gl_call_generic( { 'ExecPrompt': { @@ -136,7 +133,7 @@ def exec_prompt( 'images': images, } }, - _decode_nondet_json if format == 'json2' else _decode_nondet, + _decode_nondet_json if format == 'json' else _decode_nondet, ) From e3100c4abb8d53c333a392553dcf48cb21cbfd73 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 19:30:56 +0900 Subject: [PATCH 096/124] =?UTF-8?q?docs:=20remove=20rollback=20terminology?= =?UTF-8?q?,=20fix=20user=20error=20encoding=20docs=20=F0=9F=93=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/internal/comparisons/py-api.md | 2 +- doc/internal/node.md | 8 ++++---- .../impl-spec/01-core-architecture/02-host-interface.rst | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/internal/comparisons/py-api.md b/doc/internal/comparisons/py-api.md index 4e9b57692..6bb008cbe 100644 --- a/doc/internal/comparisons/py-api.md +++ b/doc/internal/comparisons/py-api.md @@ -80,7 +80,7 @@ So, unless leader gets some score for agreeing or disagreeing with validators it Basis function: ```rust -fn eq_principle(leader_fn: () -> bytes|rollback, validator_fn: (leaders_result: bytes|rollback) -> bool) -> bytes|rollback +fn eq_principle(leader_fn: () -> bytes|user_error, validator_fn: (leaders_result: bytes|user_error) -> bool) -> bytes|user_error ``` On top of it all sorts of API can be built, including `eq_principle(prompt_template, result_producer)` diff --git a/doc/internal/node.md b/doc/internal/node.md index a749332ad..52e34b346 100644 --- a/doc/internal/node.md +++ b/doc/internal/node.md @@ -152,7 +152,7 @@ There are following codes: #### Nondet blocks and sandbox encoding - 1 byte of result code -- result as-is (calldata for `Return`, string for `VMError|UserError`) +- result as-is (calldata for `Return`, tagged calldata for `UserError`, string for `VMError`) #### Parent VM result - 1 byte of result code @@ -170,9 +170,9 @@ There are following codes: ### Read result It has code followed by bytes, codes are: -- return, it is followed by calldata -- rollback and contract error, followed by a string; from host point of view there is no distinction between them -- just error, which is internal error, like llm's modules being absent +- return, followed by calldata +- user error, followed by tagged calldata +- vm/internal error, followed by a string ### Storage format Storage can be seen as a mapping from account address to slot address to linear memory. It supports two operations: `read` and `write`. Reading undefined memory **must** return zeroes diff --git a/doc/website/src/impl-spec/01-core-architecture/02-host-interface.rst b/doc/website/src/impl-spec/01-core-architecture/02-host-interface.rst index 72b95d5bd..5853c1994 100644 --- a/doc/website/src/impl-spec/01-core-architecture/02-host-interface.rst +++ b/doc/website/src/impl-spec/01-core-architecture/02-host-interface.rst @@ -55,7 +55,7 @@ Result Encoding **Non-deterministic Blocks and Sandbox Encoding**: - 1 byte of result code -- Result data: calldata for ``Return``, string for ``VMError`` or ``UserError`` +- Result data: calldata for ``Return``, tagged calldata for ``UserError``, string for ``VMError`` **Parent VM Result Encoding**: From 4460c8180e8d8d7263e5576c0aa5bd46e96d5ffd Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 19:31:11 +0900 Subject: [PATCH 097/124] =?UTF-8?q?docs:=20remove=20orphaned=20doc/interna?= =?UTF-8?q?l/node.md=20=F0=9F=94=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Superseded by the impl-spec (host-interface.rst + host-loop.rst). --- doc/internal/node.md | 186 ------------------------------------------- 1 file changed, 186 deletions(-) delete mode 100644 doc/internal/node.md diff --git a/doc/internal/node.md b/doc/internal/node.md deleted file mode 100644 index 52e34b346..000000000 --- a/doc/internal/node.md +++ /dev/null @@ -1,186 +0,0 @@ -## Running the GenVM - -To run a genvm, one must start a genvm process with following arguments: -- `--host` tcp-it address or `unix://` prefixed unix domain socket -- `--message` message data as json, follows [schema](../schemas/message.json) - See [example](../../executor/testdata/templates/message.json) that is used in tests - -## How to ask GenVM to quit? -Send it `SIGTERM`. If it doesn't quit in some sensible amount of time just `SIGKILL` it - -## How node receives code, message, ... from user -It is for node to decide. GenVM knows only about the calldata (and potentially message) and nothing else - -## Communication protocol -All further communication is done via socket. If the GenVM process exited before sending the result, it means that GenVM crashed. Potential bugs should be reported - -Method ids list is available as [json](../../executor/codegen/data/host-fns.json). It is advised to use it in the build system to codegen constants - -Below is pseudo code, but [real code](../../executor/testdata/runner/base_host.py) is always up to date and is as readable as this code is (see `async def host_loop(handler: IHost):`) - -``` -const ACCOUNT_ADDR_SIZE = 20 -const SLOT_ID_SIZE = 32 - -fn write_byte_slice(arr): - write_u32_le len(arr) - write_bytes arr -fn read_slice(): - len := read_u32_le - data := read_bytes(len) - return data - -loop: - method_id := read_byte - match method_id - json/methods/get_calldata: - calldata, err := host_get_calldata() - if err != json/errors/ok: - write_byte err - else: - write_byte json/errors/ok - write_byte_slice calldata - json/methods/storage_read: - read_type := read_byte as json/storage_type - address := read_bytes(ACCOUNT_ADDR_SIZE) - slot := read_bytes(SLOT_ID_SIZE) - index := read_u32_le - len := read_u32_le - data, err := host_storage_read(read_type, address, slot, index, len) - if err != json/errors/ok: - write_byte err - else: - write_byte json/errors/ok - write_bytes data # must be exactly len in size - json/methods/storage_write: - slot := read_bytes(SLOT_ID_SIZE) - index := read_u32_le - len := read_u32_le - data := read_bytes(len) - err := host_storage_write(slot, index, data) - if err != json/errors/ok: - write_byte err - else: - write_byte json/errors/ok - json/methods/consume_result: - host_result := read_slice() - # this is needed to ensure that genvm doesn't close socket before all data is read - write_byte 0x00 - break - json/methods/get_leader_nondet_result: - call_no := read_u32_le - data, err := host_get_leader_nondet_result(call_no) - if err != json/errors/ok: - write_byte err - else: - write_byte json/errors/ok - write_byte_slice result_data - json/methods/post_nondet_result: - call_no := read_u32_le - result := read_slice() - err := host_post_nondet_result(call_no, result) - if err != json/errors/ok: - write_byte err - else: - write_byte json/errors/ok - json/methods/post_message: - address := read_bytes(ACCOUNT_ADDR_SIZE) - calldata := read_slice() - message_data := read_slice() # JSON string - err := host_post_message(address, calldata, message_data) - if err != json/errors/ok: - write_byte err - else: - write_byte json/errors/ok - json/methods/consume_fuel: - gas := read_u64_le - host_consume_fuel(gas) - # note: this method doesn't send any response - json/methods/deploy_contract: - calldata := read_slice() - code := read_slice() - message_data := read_slice() # JSON string - err := host_deploy_contract(calldata, code, message_data) - if err != json/errors/ok: - write_byte err - else: - write_byte json/errors/ok - json/methods/eth_call: - address := read_bytes(ACCOUNT_ADDR_SIZE) - calldata := read_slice() - result, err := host_eth_call(address, calldata) - if err != json/errors/ok: - write_byte err - else: - write_byte json/errors/ok - write_byte_slice result - json/methods/eth_send: - address := read_bytes(ACCOUNT_ADDR_SIZE) - calldata := read_slice() - message_data := read_slice() # JSON string - err := host_eth_send(address, calldata, message_data) - if err != json/errors/ok: - write_byte err - else: - write_byte json/errors/ok - json/methods/get_balance: - address := read_bytes(ACCOUNT_ADDR_SIZE) - balance, err := host_get_balance(address) - if err != json/errors/ok: - write_byte err - else: - write_byte json/errors/ok - write_bytes balance.to_le_bytes(32) # 256-bit integer - json/methods/remaining_fuel_as_gen: - fuel, err := host_remaining_fuel_as_gen() - if err != json/errors/ok: - write_byte err - else: - write_byte json/errors/ok - write_bytes fuel.to_le_bytes(8) # 64-bit integer, must be safe integer (fits in double) -``` - -See [mock implementation](../../executor/testdata/runner/mock_host.py) - -## Types - -### VM results -There are following codes: -- `Return` -- `VMError` indicating vm-produced error that usually can't be handled -- `UserError` user-produced error - -#### Nondet blocks and sandbox encoding -- 1 byte of result code -- result as-is (calldata for `Return`, tagged calldata for `UserError`, string for `VMError`) - -#### Parent VM result -- 1 byte of result code -- calldata for `Return`, `{ "message": "string", "fingerprint": ... }` for `VMError|UserError` - -### Calldata -`get_calldata` method must return [calldata encoded](../calldata.md) bytes that conform to ABI: -```typescript -{ - method?: string, // only for non-consturctors - args: Array, - kwargs?: { [key: string]: any } -} -``` - -### Read result -It has code followed by bytes, codes are: -- return, followed by calldata -- user error, followed by tagged calldata -- vm/internal error, followed by a string - -### Storage format -Storage can be seen as a mapping from account address to slot address to linear memory. It supports two operations: `read` and `write`. Reading undefined memory **must** return zeroes - -Storage can be seen as a file system tree containing directories named as contracts which contain files named as slots, then following implementation is valid: -```bash -# read contract_a slot_b 10...100 -cat db/contract_a/slot_b.bytes /dev/null | tail -c +10 | head -c +100 -``` - -**NOTE**: calculating storage updates, hashes and so on is host's (node's) responsibility. It is [the same in geth](https://github.com/ethereum/go-ethereum/blob/67a3b087951a3f3a8e341ae32b6ec18f3553e5cc/core/state/state_object.go#L232): they have dirty override for the store From eb7bcf789692003c9abd8c93a38a909e1d33ed4d Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 19:34:30 +0900 Subject: [PATCH 098/124] =?UTF-8?q?chore(abi):=20remove=204-byte=20tagged?= =?UTF-8?q?=20calldata=20prefix=20from=20user=20error=20encoding=20?= =?UTF-8?q?=F0=9F=94=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl-spec/01-core-architecture/02-host-interface.rst | 2 +- executor/crates/sdk-rs/src/abi/entry.rs | 7 +------ executor/src/rt/vm/mod.rs | 2 -- executor/src/wasi/genlayer_sdk.rs | 9 +-------- 4 files changed, 3 insertions(+), 17 deletions(-) diff --git a/doc/website/src/impl-spec/01-core-architecture/02-host-interface.rst b/doc/website/src/impl-spec/01-core-architecture/02-host-interface.rst index 5853c1994..a898e71ce 100644 --- a/doc/website/src/impl-spec/01-core-architecture/02-host-interface.rst +++ b/doc/website/src/impl-spec/01-core-architecture/02-host-interface.rst @@ -55,7 +55,7 @@ Result Encoding **Non-deterministic Blocks and Sandbox Encoding**: - 1 byte of result code -- Result data: calldata for ``Return``, tagged calldata for ``UserError``, string for ``VMError`` +- Result data: calldata for ``Return``, calldata for ``UserError``, string for ``VMError`` **Parent VM Result Encoding**: diff --git a/executor/crates/sdk-rs/src/abi/entry.rs b/executor/crates/sdk-rs/src/abi/entry.rs index b77315967..d21c6025d 100644 --- a/executor/crates/sdk-rs/src/abi/entry.rs +++ b/executor/crates/sdk-rs/src/abi/entry.rs @@ -428,12 +428,7 @@ pub mod contract_def { Ok(LeaderResult::Return(value)) } ResultCode::UserError => { - if rest.len() < 4 || rest[..4] != [0u8; 4] { - return Err(ConsensusStageParseError::DecodeError( - "missing tagged calldata prefix in user error".to_owned(), - )); - } - let value = calldata::decode(&rest[4..]) + let value = calldata::decode(rest) .map_err(|e| ConsensusStageParseError::DecodeError(e.to_string()))?; Ok(LeaderResult::UserError(value)) } diff --git a/executor/src/rt/vm/mod.rs b/executor/src/rt/vm/mod.rs index a8656f1a8..552d04fe6 100644 --- a/executor/src/rt/vm/mod.rs +++ b/executor/src/rt/vm/mod.rs @@ -91,12 +91,10 @@ impl RunOk { } RunOk::UserError(val) => { let mut res = vec![ResultCode::UserError as u8]; - res.extend_from_slice(&0u32.to_le_bytes()); match val { calldata::unparsed::Maybe::Materialized(value) => { res.extend_from_slice(&calldata::encode(value)); } - // Already-encoded calldata bytes. calldata::unparsed::Maybe::Checked(raw) => { res.extend_from_slice(&raw.0); } diff --git a/executor/src/wasi/genlayer_sdk.rs b/executor/src/wasi/genlayer_sdk.rs index 265c76b21..86a7cf9f6 100644 --- a/executor/src/wasi/genlayer_sdk.rs +++ b/executor/src/wasi/genlayer_sdk.rs @@ -1735,14 +1735,7 @@ impl ContextVFS<'_> { )) } x if x == ResultCode::UserError as u8 => { - if rest.len() < 4 || rest[..4] != [0u8; 4] { - return Err(generated::types::Error::trap(crate::anyhow_to_wasmtime( - anyhow::anyhow!( - "invalid user error encoding: missing tagged calldata prefix" - ), - ))); - } - let val = calldata::decode(&rest[4..]).map_err(|e| { + let val = calldata::decode(rest).map_err(|e| { generated::types::Error::trap(crate::anyhow_to_wasmtime( anyhow::anyhow!(e), )) From 67fa3b4b7899b0ddb7fb89c9f7083989a184cbd2 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 19:57:16 +0900 Subject: [PATCH 099/124] =?UTF-8?q?feat(fees):=20generalize=20bucket=5Fno?= =?UTF-8?q?=20to=20accept=20int=20or=20array=20of=20ints=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bucket_no in genvm.yaml now supports either a single integer or an array. When the delta expression returns a scalar it is charged against all listed buckets; when it returns an array the lengths must match. All subtractions are atomic (all-or-nothing). --- doc/schemas/default-config.json | 19 +- executor/src/config.rs | 36 +++- executor/src/exe/run.rs | 11 +- executor/src/rt/fees.rs | 304 ++++++++++++++++++------------ executor/src/wasi/genlayer_sdk.rs | 31 +-- 5 files changed, 255 insertions(+), 146 deletions(-) diff --git a/doc/schemas/default-config.json b/doc/schemas/default-config.json index 7c136a6be..3f56aa017 100644 --- a/doc/schemas/default-config.json +++ b/doc/schemas/default-config.json @@ -324,9 +324,22 @@ "type": "object", "properties": { "bucket_no": { - "type": "integer", - "minimum": 0, - "maximum": 255 + "oneOf": [ + { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + { + "type": "array", + "items": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "minItems": 1 + } + ] }, "subtract_on_start_expr": { "type": "string", diff --git a/executor/src/config.rs b/executor/src/config.rs index da0466b26..6483f3d59 100644 --- a/executor/src/config.rs +++ b/executor/src/config.rs @@ -15,9 +15,43 @@ fn default_fee_expr_zero() -> String { "0".to_owned() } +fn deserialize_bucket_nos<'de, D>(d: D) -> Result, D::Error> +where + D: serde::Deserializer<'de>, +{ + use serde::de; + + struct Visitor; + impl<'de> de::Visitor<'de> for Visitor { + type Value = Vec; + fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.write_str("an integer or array of integers") + } + fn visit_u64(self, v: u64) -> Result, E> { + u8::try_from(v) + .map(|b| vec![b]) + .map_err(|_| E::custom(format!("bucket_no {v} exceeds u8 range"))) + } + fn visit_i64(self, v: i64) -> Result, E> { + u8::try_from(v) + .map(|b| vec![b]) + .map_err(|_| E::custom(format!("bucket_no {v} out of u8 range"))) + } + fn visit_seq>(self, mut seq: A) -> Result, A::Error> { + let mut v = Vec::new(); + while let Some(n) = seq.next_element::()? { + v.push(n); + } + Ok(v) + } + } + d.deserialize_any(Visitor) +} + #[derive(Clone, Deserialize, Debug)] pub struct FeesBucketConfig { - pub bucket_no: u8, + #[serde(deserialize_with = "deserialize_bucket_nos")] + pub bucket_no: Vec, /// Cost charged once, up-front, when the bucket is created /// (the fixed part of `start + sum of per-change`). #[serde(default = "default_fee_expr_zero")] diff --git a/executor/src/exe/run.rs b/executor/src/exe/run.rs index 18c3673d8..44a81157f 100644 --- a/executor/src/exe/run.rs +++ b/executor/src/exe/run.rs @@ -126,13 +126,14 @@ pub fn handle(args: Args, mut config: config::Config) -> Result<()> { .collect::>>()?; let max_bucket_no = [ - config.fees.storage.bucket_no, - config.fees.message_receipt.bucket_no, - config.fees.nondet_output.bucket_no, - config.fees.message_fee.bucket_no, - config.fees.event.bucket_no, + &config.fees.storage.bucket_no, + &config.fees.message_receipt.bucket_no, + &config.fees.nondet_output.bucket_no, + &config.fees.message_fee.bucket_no, + &config.fees.event.bucket_no, ] .into_iter() + .flat_map(|v| v.iter().copied()) .max() .unwrap_or(0); diff --git a/executor/src/rt/fees.rs b/executor/src/rt/fees.rs index 6d35bd49a..150471822 100644 --- a/executor/src/rt/fees.rs +++ b/executor/src/rt/fees.rs @@ -85,10 +85,7 @@ pub fn fee_params_value_external( Value::Object(Arc::new(m)) } -fn value_to_u256(value: genvm_common::expr::Value) -> anyhow::Result { - let rational = value - .into_rational() - .map_err(|e| anyhow::anyhow!("fee expression must yield a number: {e}"))?; +fn rational_to_u256(rational: num_rational::BigRational) -> anyhow::Result { anyhow::ensure!( rational.is_integer(), "fee expression must yield an integer, got {rational}" @@ -105,6 +102,35 @@ fn value_to_u256(value: genvm_common::expr::Value) -> anyhow::Result anyhow::Result> { + match value { + genvm_common::expr::Value::Rational(r) => { + let cost = rational_to_u256(r)?; + Ok(vec![cost; bucket_count]) + } + genvm_common::expr::Value::Array(arr) => { + anyhow::ensure!( + arr.len() == bucket_count, + "fee expression returned array of length {} but bucket_no has {bucket_count} entries", + arr.len(), + ); + arr.iter() + .map(|v| { + let r = v + .clone() + .into_rational() + .map_err(|e| anyhow::anyhow!("fee array element must be a number: {e}"))?; + rational_to_u256(r) + }) + .collect() + } + other => anyhow::bail!("fee expression must yield a number or array, got {other:?}",), + } +} + /// Parses `\node = ` and applies it to `node`, so the result /// closes over `node` (and the prelude). The `delta` form additionally /// returns a `\attrs = ...` function ready to be applied per charge. @@ -127,20 +153,24 @@ fn eval_with_node( /// A fee bucket: total = `subtract_on_start` (charged once by /// [`DataLimit::consume_initial`]) + Σ `delta(attrs)`. `delta` is a function /// closing over `node`/the prelude. +/// +/// `bucket_nos` can target multiple on-chain buckets. When the delta expression +/// returns a scalar it is charged identically against every bucket; when it +/// returns an array the lengths must match and each element is charged to the +/// corresponding bucket. All subtractions are atomic (all-or-nothing). struct Bucket { - bucket_no: u8, - subtract_on_start: primitive_types::U256, + bucket_nos: Vec, + subtract_on_start: Vec, delta: genvm_common::expr::Value, - /// VM error reported when `subtract_on_start` underflows the bucket. oom_error: abi::consts::VmError, - total_consumed: tokio::sync::Mutex, + total_consumed: Vec>, } impl std::fmt::Debug for Bucket { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("Bucket") - .field("bucket_no", &self.bucket_no) + .field("bucket_nos", &self.bucket_nos) .field("subtract_on_start", &self.subtract_on_start) .finish() } @@ -152,27 +182,46 @@ fn build_bucket( node: &genvm_common::expr::Value, oom_error: abi::consts::VmError, ) -> anyhow::Result { - let subtract_on_start = value_to_u256(eval_with_node( - prelude, - "subtract_on_start", - &cfg.subtract_on_start_expr, - node, - )?)?; + let n = cfg.bucket_no.len(); + anyhow::ensure!(n > 0, "bucket_no must have at least one entry"); + + let subtract_on_start = value_to_u256_vec( + eval_with_node( + prelude, + "subtract_on_start", + &cfg.subtract_on_start_expr, + node, + )?, + n, + )?; let delta = eval_with_node(prelude, "delta", &cfg.delta_expr, node)?; Ok(Bucket { - bucket_no: cfg.bucket_no, + bucket_nos: cfg.bucket_no.clone(), subtract_on_start, delta, oom_error, - total_consumed: Default::default(), + total_consumed: (0..n).map(|_| Default::default()).collect(), }) } -#[derive(Debug, Clone, Copy)] +/// Per-bucket cost vector returned by `calculate_*` methods. +#[derive(Debug, Clone)] +pub struct CostVec(pub Vec); + +impl CostVec { + pub fn sum(&self) -> primitive_types::U256 { + self.0 + .iter() + .copied() + .fold(primitive_types::U256::zero(), |a, b| a + b) + } +} + +#[derive(Debug, Clone)] pub struct MessageFeeConsumption { - pub message_fee: primitive_types::U256, - pub receipt_fee: primitive_types::U256, + pub message_fee: CostVec, + pub receipt_fee: CostVec, } #[derive(Debug, Clone, Copy, Default, genlayer_calldata::Encode)] @@ -269,14 +318,14 @@ impl DataLimit { &self, bucket: &Bucket, vars: &[(&str, genvm_common::expr::Value)], - ) -> anyhow::Result { + ) -> anyhow::Result { match bucket .delta .apply_with(attrs_object(vars), no_free_vars) .map_err(|e| anyhow::anyhow!("{e}")) - .and_then(value_to_u256) + .and_then(|v| value_to_u256_vec(v, bucket.bucket_nos.len())) { - Ok(cost) => Ok(cost), + Ok(costs) => Ok(CostVec(costs)), Err(e) => { log_error!(error:ah = e; "failed to evaluate fee expression"); Err(e).context("failed to evaluate fee expression") @@ -289,50 +338,78 @@ impl DataLimit { bucket: &Bucket, vars: &[(&str, genvm_common::expr::Value)], ) -> anyhow::Result { - let cost = self.calculate_bucket(bucket, vars)?; - Ok(self.consume_bucket_raw(bucket, cost).await) + let costs = self.calculate_bucket(bucket, vars)?; + Ok(self.consume_bucket_raw(bucket, &costs.0).await) } - async fn consume_bucket_raw(&self, bucket: &Bucket, cost: primitive_types::U256) -> bool { + async fn consume_bucket_raw(&self, bucket: &Bucket, costs: &[primitive_types::U256]) -> bool { let mut buckets = self.buckets.lock().await; - let Some(remaining) = buckets.get_mut(bucket.bucket_no as usize) else { - log_warn!(bucket = bucket.bucket_no; "consume_bucket: bucket index out of range"); - return false; - }; - if *remaining >= cost { - *remaining -= cost; + for (idx, (&bno, &cost)) in bucket.bucket_nos.iter().zip(costs.iter()).enumerate() { + let Some(remaining) = buckets.get(bno as usize) else { + log_warn!(bucket = bno; "consume_bucket: bucket index out of range"); + return false; + }; + if *remaining < cost { + log_warn!( + bucket = bno, + cost:display = cost, + remaining:display = *remaining; + "consume_bucket: insufficient funds" + ); + return false; + } + // when the same bucket_no appears more than once, verify + // cumulative cost fits + let mut cumulative = cost; + for (&prev_bno, &prev_cost) in bucket.bucket_nos[..idx].iter().zip(costs[..idx].iter()) + { + if prev_bno == bno { + cumulative += prev_cost; + } + } + if *remaining < cumulative { + log_warn!( + bucket = bno, + cumulative:display = cumulative, + remaining:display = *remaining; + "consume_bucket: insufficient funds (cumulative)" + ); + return false; + } + } + for (i, (&bno, &cost)) in bucket.bucket_nos.iter().zip(costs.iter()).enumerate() { + buckets[bno as usize] -= cost; log_debug!( - bucket = bucket.bucket_no, + bucket = bno, cost:display = cost, - remaining:display = *remaining; + remaining:display = buckets[bno as usize]; "consume_bucket: ok" ); - std::mem::drop(buckets); - *bucket.total_consumed.lock().await += cost; - - true - } else { - log_warn!( - bucket = bucket.bucket_no, - cost:display = cost, - remaining:display = *remaining; - "consume_bucket: insufficient funds" - ); - false + *bucket.total_consumed[i].lock().await += cost; } + std::mem::drop(buckets); + true } pub async fn remaining(&self) -> Vec { self.buckets.lock().await.clone() } + async fn sum_consumed(bucket: &Bucket) -> primitive_types::U256 { + let mut total = primitive_types::U256::zero(); + for tc in &bucket.total_consumed { + total += *tc.lock().await; + } + total + } + pub async fn consumed(&self) -> BucketsConsumed { BucketsConsumed { - storage: *self.storage.total_consumed.lock().await, - message_receipt: *self.message_receipt.total_consumed.lock().await, - nondet_output: *self.nondet_output.total_consumed.lock().await, - message_fee: *self.message_fee.total_consumed.lock().await, - event: *self.event.total_consumed.lock().await, + storage: Self::sum_consumed(&self.storage).await, + message_receipt: Self::sum_consumed(&self.message_receipt).await, + nondet_output: Self::sum_consumed(&self.nondet_output).await, + message_fee: Self::sum_consumed(&self.message_fee).await, + event: Self::sum_consumed(&self.event).await, } } @@ -348,31 +425,17 @@ impl DataLimit { &self.message_fee, &self.event, ] { - let mut buckets = self.buckets.lock().await; - let Some(remaining) = buckets.get_mut(bucket.bucket_no as usize) else { + if !self + .consume_bucket_raw(bucket, &bucket.subtract_on_start.clone()) + .await + { return Some(rt::errors::VMError( bucket.oom_error.clone(), Some(anyhow::anyhow!( - "consume_initial: bucket {} index out of range", - bucket.bucket_no + "subtract_on_start exceeds bucket {:?} total", + bucket.bucket_nos )), )); - }; - match remaining.checked_sub(bucket.subtract_on_start) { - Some(v) => { - *remaining = v; - std::mem::drop(buckets); - *bucket.total_consumed.lock().await += bucket.subtract_on_start; - } - None => { - return Some(rt::errors::VMError( - bucket.oom_error.clone(), - Some(anyhow::anyhow!( - "subtract_on_start exceeds bucket {} total", - bucket.bucket_no - )), - )); - } } } None @@ -386,7 +449,7 @@ impl DataLimit { pub fn calculate_message_receipt( &self, params: MessageReceiptParams, - ) -> anyhow::Result { + ) -> anyhow::Result { self.calculate_bucket( &self.message_receipt, &[ @@ -414,15 +477,15 @@ impl DataLimit { blob_size: u64, topics_count: u64, ) -> anyhow::Result> { - let cost = self.calculate_bucket( + let costs = self.calculate_bucket( &self.event, &[ ("blobSize", num(blob_size)), ("topicsCount", num(topics_count)), ], )?; - if self.consume_bucket_raw(&self.event, cost).await { - Ok(Some(cost)) + if self.consume_bucket_raw(&self.event, &costs.0).await { + Ok(Some(costs.sum())) } else { Ok(None) } @@ -432,7 +495,7 @@ impl DataLimit { &self, on: abi::gl_call::On, matched_fee_params: &genvm_common::domain::fees::InternalMessageParams, - ) -> anyhow::Result { + ) -> anyhow::Result { self.calculate_bucket( &self.message_fee, &[ @@ -447,67 +510,64 @@ impl DataLimit { .context("calculating message fee internal") } - pub async fn consume_message_fee( - &self, - cost_fee: primitive_types::U256, - cost_receipt: primitive_types::U256, - ) -> bool { - if self.message_fee.bucket_no == self.message_receipt.bucket_no { - let Some(sum) = cost_fee.checked_add(cost_receipt) else { - log_warn!( - cost_fee:display = cost_fee, - cost_receipt:display = cost_receipt; - "consume_message_fee: overflow adding fee + receipt" - ); - return false; - }; - return self.consume_bucket_raw(&self.message_fee, sum).await; - } - + pub async fn consume_message_fee(&self, cost_fee: &CostVec, cost_receipt: &CostVec) -> bool { let mut buckets = self.buckets.lock().await; - if cost_fee > buckets[self.message_fee.bucket_no as usize] { - log_warn!( - bucket = self.message_fee.bucket_no, - cost_fee:display = cost_fee, - remaining:display = buckets[self.message_fee.bucket_no as usize]; - "consume_message_fee: insufficient funds for fee" - ); - return false; + // Build a cumulative deduction map: bucket_index → total to subtract. + let mut deductions: std::collections::BTreeMap = + std::collections::BTreeMap::new(); + + for (&bno, &cost) in self.message_fee.bucket_nos.iter().zip(cost_fee.0.iter()) { + *deductions.entry(bno).or_default() += cost; + } + for (&bno, &cost) in self + .message_receipt + .bucket_nos + .iter() + .zip(cost_receipt.0.iter()) + { + *deductions.entry(bno).or_default() += cost; } - if cost_receipt > buckets[self.message_receipt.bucket_no as usize] { - log_warn!( - bucket = self.message_receipt.bucket_no, - cost_receipt:display = cost_receipt, - remaining:display = buckets[self.message_receipt.bucket_no as usize]; - "consume_message_fee: insufficient funds for receipt" - ); - return false; + // Check all buckets first (atomic: all-or-nothing). + for (&bno, &total) in &deductions { + let Some(remaining) = buckets.get(bno as usize) else { + log_warn!(bucket = bno; "consume_message_fee: bucket index out of range"); + return false; + }; + if *remaining < total { + log_warn!( + bucket = bno, + cost:display = total, + remaining:display = *remaining; + "consume_message_fee: insufficient funds" + ); + return false; + } } - buckets[self.message_fee.bucket_no as usize] -= cost_fee; - buckets[self.message_receipt.bucket_no as usize] -= cost_receipt; + // Apply all deductions. + for (&bno, &total) in &deductions { + buckets[bno as usize] -= total; + } std::mem::drop(buckets); - *self.message_fee.total_consumed.lock().await += cost_fee; - *self.message_receipt.total_consumed.lock().await += cost_receipt; - - log_debug!( - fee_bucket = self.message_fee.bucket_no, - cost_fee:display = cost_fee, - receipt_bucket = self.message_receipt.bucket_no, - cost_receipt:display = cost_receipt; - "consume_message_fee: ok" - ); + // Update per-category consumed trackers. + for (i, &cost) in cost_fee.0.iter().enumerate() { + *self.message_fee.total_consumed[i].lock().await += cost; + } + for (i, &cost) in cost_receipt.0.iter().enumerate() { + *self.message_receipt.total_consumed[i].lock().await += cost; + } + log_debug!("consume_message_fee: ok"); true } pub fn calculate_message_fee_external( &self, matched_fee_params: &genvm_common::domain::fees::ExternalMessageParams, - ) -> anyhow::Result { + ) -> anyhow::Result { self.calculate_bucket( &self.message_fee, &[ diff --git a/executor/src/wasi/genlayer_sdk.rs b/executor/src/wasi/genlayer_sdk.rs index 86a7cf9f6..ce3c334ae 100644 --- a/executor/src/wasi/genlayer_sdk.rs +++ b/executor/src/wasi/genlayer_sdk.rs @@ -47,10 +47,11 @@ async fn consume_message_fee_internal( .calculate_message_fee_internal(on, &fee_params) .map_err(|x| generated::types::Error::trap(anyhow_to_wasmtime(x)))?; - if fee_cost > node.budget { + let fee_total = fee_cost.sum(); + if fee_total > node.budget { log_warn!( node:cd = *node, - fee_cost:cd = fee_cost, + fee_cost:cd = fee_total, budget: cd = node.budget; "message fee cost exceeds node budget" ); @@ -74,20 +75,19 @@ async fn consume_message_fee_internal( if !shared_data .data_fees_limit - .consume_message_fee(fee_cost, receipt_cost) + .consume_message_fee(&fee_cost, &receipt_cost) .await { log_warn!( node:cd = *node, - fee_cost:cd = fee_cost, - receipt_cost: cd = receipt_cost, + fee_cost:cd = fee_total, buckets:? = shared_data.data_fees_limit; "not enough remaining fee limit to consume message fee" ); return Err(oom_trap(abi::consts::VmError::oom().fees().internal())); } - node.budget -= fee_cost; + node.budget -= fee_total; Ok(rt::fees::MessageFeeConsumption { message_fee: fee_cost, @@ -115,7 +115,8 @@ async fn consume_message_fee_external( .calculate_message_fee_external(¶ms) .map_err(|x| generated::types::Error::trap(anyhow_to_wasmtime(x)))?; - if fee_cost > node.budget { + let fee_total = fee_cost.sum(); + if fee_total > node.budget { return Err(oom_trap(abi::consts::VmError::oom().fees().external())); } @@ -132,13 +133,13 @@ async fn consume_message_fee_external( if !shared_data .data_fees_limit - .consume_message_fee(fee_cost, receipt_cost) + .consume_message_fee(&fee_cost, &receipt_cost) .await { return Err(oom_trap(abi::consts::VmError::oom().fees().external())); } - node.budget -= fee_cost; + node.budget -= fee_total; Ok(rt::fees::MessageFeeConsumption { message_fee: fee_cost, @@ -666,8 +667,8 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { address, calldata, value, - message_fee: fees.message_fee, - receipt_fee: fees.receipt_fee, + message_fee: fees.message_fee.sum(), + receipt_fee: fees.receipt_fee.sum(), fee_params: matched_params, }); @@ -982,8 +983,8 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { calldata, value, on, - message_fee: fees.message_fee, - receipt_fee: fees.receipt_fee, + message_fee: fees.message_fee.sum(), + receipt_fee: fees.receipt_fee.sum(), fee_params, subtree, }, @@ -1087,8 +1088,8 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { value, on, salt_nonce, - message_fee: fees.message_fee, - receipt_fee: fees.receipt_fee, + message_fee: fees.message_fee.sum(), + receipt_fee: fees.receipt_fee.sum(), fee_params, subtree, }, From 54fb84896041be1d68cb25e6c1807eef605aa38f Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 19:59:29 +0900 Subject: [PATCH 100/124] =?UTF-8?q?fix(webdriver):=20harden=20SSRF=20guard?= =?UTF-8?q?=20against=20popups=20and=20missing=20IP=20ranges=20?= =?UTF-8?q?=F0=9F=94=92=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Install SSRF guard on popup pages via targetcreated listener. Block 198.18.0.0/15 (benchmarking) and fec0::/10 (deprecated site-local). --- modules/webdriver/src/prj/src/index.ts | 6 ++++++ modules/webdriver/src/prj/src/ssrf.ts | 2 ++ 2 files changed, 8 insertions(+) diff --git a/modules/webdriver/src/prj/src/index.ts b/modules/webdriver/src/prj/src/index.ts index f5fa0cd5f..d948c6ac4 100644 --- a/modules/webdriver/src/prj/src/index.ts +++ b/modules/webdriver/src/prj/src/index.ts @@ -248,6 +248,12 @@ async function renderPageWithBrowser( try { await ssrf.installSsrfGuard(page); + context.on('targetcreated', async (target) => { + const p = await target.page(); + if (p && p !== page) { + await ssrf.installSsrfGuard(p); + } + }); page.setViewport({ width: 1920 / 2, height: 1080 / 2 }); return await withHeapMonitor(page, maxPageHeapMB, async () => { diff --git a/modules/webdriver/src/prj/src/ssrf.ts b/modules/webdriver/src/prj/src/ssrf.ts index 354878b14..336c53f1f 100644 --- a/modules/webdriver/src/prj/src/ssrf.ts +++ b/modules/webdriver/src/prj/src/ssrf.ts @@ -56,6 +56,7 @@ function ipv4IsBad(ip: string): boolean { (a === 192 && b === 168) || // 192.168.0.0/16 private (a === 100 && b >= 64 && b <= 127) || // 100.64.0.0/10 CGNAT (a === 192 && b === 0 && c === 2) || // 192.0.2.0/24 documentation + (a === 198 && b >= 18 && b <= 19) || // 198.18.0.0/15 benchmarking (a === 198 && b === 51 && c === 100) || // 198.51.100.0/24 documentation (a === 203 && b === 0 && c === 113) || // 203.0.113.0/24 documentation a >= 224 // 224.0.0.0/3 multicast + reserved + broadcast @@ -152,6 +153,7 @@ function ipv6IsBad(ip: string): boolean { return ( (first & 0xfe00) === 0xfc00 || // fc00::/7 unique-local (first & 0xffc0) === 0xfe80 || // fe80::/10 link-local + (first & 0xffc0) === 0xfec0 || // fec0::/10 deprecated site-local (first & 0xff00) === 0xff00 // ff00::/8 multicast ); } From 71d562090286e9de3116e3cf80ccf477ac97e05a Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 20:14:26 +0900 Subject: [PATCH 101/124] =?UTF-8?q?docs:=20add=20missing=20gl.vm=20migrati?= =?UTF-8?q?on=20notes=20to=20v0.3=20changelog=20=F0=9F=93=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Document the run_nondet rename (old run_nondet -> run_nondet_default, old run_nondet_unsafe -> run_nondet) as a silent semantic change, spawn_sandbox permission split, new register_runner/map_file/gvm32, the keccak path move, and the NewType -> Annotated alias change. Also fix short RST section underlines. --- .../src/python-sdk/changelog-notes/v0.3.rst | 76 ++++++++++++++++--- 1 file changed, 66 insertions(+), 10 deletions(-) diff --git a/doc/website/src/python-sdk/changelog-notes/v0.3.rst b/doc/website/src/python-sdk/changelog-notes/v0.3.rst index b54bd1dfc..9798de297 100644 --- a/doc/website/src/python-sdk/changelog-notes/v0.3.rst +++ b/doc/website/src/python-sdk/changelog-notes/v0.3.rst @@ -7,7 +7,7 @@ Migration Guide v0.3.0 introduces a major restructuring of the standard library. The ``genlayer.gl`` and ``genlayer.py`` intermediate packages are removed. All public API is now accessible directly under the ``genlayer`` namespace. Import Pattern -~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~ The recommended import pattern has changed: @@ -23,7 +23,7 @@ The recommended import pattern has changed: The ``from genlayer import *`` star-import previously brought ``gl`` (a lazy proxy to ``genlayer.gl``), all types, and storage names into scope. Now ``import genlayer as gl`` gives you direct access to submodules (``gl.contract``, ``gl.vm``, ``gl.message``, ``gl.chain``, etc.), decorators (``gl.public``, ``gl.private``), and storage types (``gl.TreeMap``, ``gl.DynArray``, ``gl.Array``). The ``from genlayer.types import *`` import brings the type aliases (``u8``..``u256``, ``i8``..``i256``, ``Address``, ``bigint``, etc.) into local scope. Module Path Changes -~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~ All ``genlayer.py.*`` and ``genlayer.gl.*`` paths are removed. Here is the mapping: @@ -35,6 +35,8 @@ All ``genlayer.py.*`` and ``genlayer.gl.*`` paths are removed. Here is the mappi - v0.3.0 * - ``genlayer.py.types`` - ``genlayer.types`` + * - ``genlayer.py.keccak`` + - ``genlayer.types.keccak`` * - ``genlayer.py.calldata`` - ``genlayer.calldata`` * - ``genlayer.py.storage`` @@ -54,8 +56,19 @@ All ``genlayer.py.*`` and ``genlayer.gl.*`` paths are removed. Here is the mappi * - ``genlayer.gl.advanced`` - removed (see below) +.. note:: + Type aliases (``u8``..``u256``, ``i8``..``i256``) are no longer ``typing.NewType`` instances; they are now ``typing.Annotated[int, ...]``. They still work as type annotations, but they are no longer callable, so the ``u256(0)`` wrapping is gone — pass a plain ``int`` instead: + + .. code-block:: python + + # v0.2.x + gl.contract.deploy(code=source, value=u256(1000), salt_nonce=u256(42)) + + # v0.3.0 + gl.contract.deploy(code=source, value=1000, salt_nonce=42) + Contract Declaration -~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~ ``gl.Contract`` is now ``gl.contract.Contract``: @@ -70,7 +83,7 @@ Contract Declaration ... Contract Interaction -~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~ Functions for interacting with other contracts have been renamed and moved into ``gl.contract``: @@ -99,7 +112,7 @@ The ``ContractProxy`` type is renamed to ``gl.contract.Proxy``. Contract proxies, ``Contract`` itself, and the new ``gl.chain.Account`` all implement the ``gl.chain.IAccount`` protocol, exposing ``address``, ``balance``, and ``emit_transfer(value, *, on=...)``. Value Transfers and ``on=`` Parameter -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Write-call and deploy APIs now take an ``on`` keyword controlling when the message is applied, with values ``'accepted'`` or ``'finalized'`` (default ``'finalized'``): @@ -160,7 +173,7 @@ The ``Event`` class has moved from ``genlayer.gl`` to ``genlayer.chain``: ``gl.advanced.emit_raw_event(topics, blob)`` is now ``gl.chain.Event.emit_raw(topics, blob)``. Advanced / Error Handling -~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~ The ``genlayer.gl.advanced`` module is removed. Its functionality has been relocated: @@ -202,6 +215,45 @@ Trace functions have moved from ``genlayer.gl`` to ``genlayer.vm``: gl.vm.trace("debug message") gl.vm.trace_time_micro() +Non-deterministic Execution (``gl.vm``) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. warning:: + ``gl.vm.run_nondet`` **changed meaning**. The two ``run_nondet`` functions were renamed: + + * the old ``run_nondet_unsafe`` (no validator sandbox) is now ``run_nondet``; + * the old ``run_nondet`` (safe, validator runs in a sandbox) is now ``run_nondet_default``. + + Code that called ``gl.vm.run_nondet`` still compiles but now silently uses the + *unsafe* variant. To keep the previous behavior, switch to ``gl.vm.run_nondet_default``: + + .. code-block:: python + + # v0.2.x (safe) # v0.3.0 (same behavior) + gl.vm.run_nondet(...) gl.vm.run_nondet_default(...) + + # v0.2.x (unsafe) # v0.3.0 (same behavior) + gl.vm.run_nondet_unsafe(...) gl.vm.run_nondet(...) + +The high-level equivalence principles (``gl.eq_principle.*``) are unaffected — they were updated internally. + +``gl.vm.spawn_sandbox`` replaced the single ``allow_write_ops`` flag with three granular permissions, each effective only if the current VM holds it: + +.. code-block:: python + + # v0.2.x + gl.vm.spawn_sandbox(fn, allow_write_ops=True) + + # v0.3.0 + gl.vm.spawn_sandbox( + fn, + allow_write_storage=True, + allow_send_messages=True, + allow_register_runners=True, + ) + +Two runtime helpers were added: ``gl.vm.register_runner(code)`` registers a runner archive and returns its ``custom:`` id, and ``gl.vm.map_file(runner, path_in_runner, path_in_vfs)`` maps a file from a runner into the VM filesystem. + Storage ~~~~~~~ @@ -236,17 +288,17 @@ Decorators def balance_of(self, owner: Address) -> u256: ... Non-deterministic Operations -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``gl.nondet`` now raises a dedicated ``gl.nondet.NondetException`` (with ``causes`` and ``ctx``) on errors instead of a bare exception. Web request helpers (``gl.nondet.web.get``/``post``/``put``/...) accept a ``sign: bool`` keyword to sign outbound requests with the contract's identity. Environment Detection -~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~ -A new top-level ``gl.IS_IN_VM`` boolean indicates whether code is running inside the GenVM, which is useful for code that is shared between contracts and off-chain tooling. The raw WASI module is available as ``gl.wasi``. +A new top-level ``gl.IS_IN_VM`` boolean indicates whether code is running inside the GenVM, which is useful for code that is shared between contracts and off-chain tooling. The raw WASI module is available as ``gl.wasi``. A ``gl.gvm32`` module provides Crockford Base32 ``encode``/``decode`` helpers (mirroring the Rust ``genlayer_sdk::gvm32`` implementation). Summary of Renames -~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~ .. list-table:: :header-rows: 1 @@ -274,6 +326,10 @@ Summary of Renames - ``gl.vm.trace(...)`` * - ``gl.trace_time_micro()`` - ``gl.vm.trace_time_micro()`` + * - ``gl.vm.run_nondet_unsafe(...)`` + - ``gl.vm.run_nondet(...)`` + * - ``gl.vm.run_nondet(...)`` + - ``gl.vm.run_nondet_default(...)`` * - ``gl.message_raw`` - ``gl.message.raw`` * - ``gl.storage.allow_storage`` From 0857d33205afb1cf80cb27b5457b150878b9a7e5 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 20:27:03 +0900 Subject: [PATCH 102/124] =?UTF-8?q?chore(abi):=20move=20major=20to=20root?= =?UTF-8?q?=20slot=20offset=200=20=F0=9F=94=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reorder root slot fields so `major` is the first byte read, enabling early rejection of incompatible contracts before touching any other storage. --- .../spec/04-contract-interface/03-storage.rst | 16 +- .../04-upgradability.rst | 2 +- doc/website/src/spec/appendix/constants.rst | 384 ++++++++++++++++++ executor/crates/sdk-rs/src/abi/consts.rs | 10 +- .../src/genlayer/storage/root.py | 12 +- .../src/genlayer/vm/public_abi.py | 10 +- 6 files changed, 409 insertions(+), 25 deletions(-) create mode 100644 doc/website/src/spec/appendix/constants.rst diff --git a/doc/website/src/spec/04-contract-interface/03-storage.rst b/doc/website/src/spec/04-contract-interface/03-storage.rst index 19a061244..58182d53b 100644 --- a/doc/website/src/spec/04-contract-interface/03-storage.rst +++ b/doc/website/src/spec/04-contract-interface/03-storage.rst @@ -44,19 +44,19 @@ Root Slot the following data: -- ``contract_instance``: (offset 0) Reference to the contract instance data. -- ``code``: (offset 1) The contract's code. Slot contains 4 bytes little-endian length followed by data -- ``locked_slots``: (offset 2) A list of storage :term:`SlotID`\s that cannot be modified by non-upgraders. - Slot contains 4 bytes little-endian length followed length arrays of 32 byte :term:`SlotID`\s -- ``upgraders``: (offset 3) A list of addresses that are authorized to modify the contract code and locked slots. - Slot contains 4 bytes little-endian length followed length arrays of 20 byte addresses -- ``major``: (offset 4) Single octet (``u8``) identifying the major version of the public ABI +- ``major``: (offset 0) Single octet (``u8``) identifying the major version of the public ABI that the contract was built against. It is written at deploy time (the value is detected from the contract package — see :doc:`04-upgradability` and the impl-spec for the detection flow) and read on every load so :term:`GenVM` can refuse to execute a contract whose public ABI major does not match the host's ``CURRENT_MAJOR``. +- ``contract_instance``: (offset 1) Reference to the contract instance data. +- ``code``: (offset 2) The contract's code. Slot contains 4 bytes little-endian length followed by data +- ``locked_slots``: (offset 3) A list of storage :term:`SlotID`\s that cannot be modified by non-upgraders. + Slot contains 4 bytes little-endian length followed length arrays of 32 byte :term:`SlotID`\s +- ``upgraders``: (offset 4) A list of addresses that are authorized to modify the contract code and locked slots. + Slot contains 4 bytes little-endian length followed length arrays of 20 byte addresses - ``code_slot``: (offset 5) A raw 32-byte :term:`SlotID`. If it is all-zero (the default), - the contract code is read from the ``code`` slot (offset 1); otherwise the code is read from + the contract code is read from the ``code`` slot (offset 2); otherwise the code is read from the slot it points to (same 4-byte-length-prefixed layout). This lets a contract serve its code from an arbitrary slot, including one shared via a ``chain:
::`` runner id. diff --git a/doc/website/src/spec/04-contract-interface/04-upgradability.rst b/doc/website/src/spec/04-contract-interface/04-upgradability.rst index e27226018..f75607c6e 100644 --- a/doc/website/src/spec/04-contract-interface/04-upgradability.rst +++ b/doc/website/src/spec/04-contract-interface/04-upgradability.rst @@ -47,7 +47,7 @@ Sub-VMs created by ``Sandbox`` and ``RunNondet`` cannot reach storage at all Contract Major Version ---------------------- -The ``major`` field of :ref:`genvm-def-root-slot` (offset 4) stores the public-ABI major version +The ``major`` field of :ref:`genvm-def-root-slot` (offset 0) stores the public-ABI major version that the contract was built against. On every load :term:`GenVM` compares this byte to its own ``CURRENT_MAJOR`` constant and refuses to execute a contract whose major differs. diff --git a/doc/website/src/spec/appendix/constants.rst b/doc/website/src/spec/appendix/constants.rst new file mode 100644 index 000000000..0a4140517 --- /dev/null +++ b/doc/website/src/spec/appendix/constants.rst @@ -0,0 +1,384 @@ +Constants +========= + +.. _gvm-def-enum-result-code: + +result_code +----------- + +Type: u8 + +.. _gvm-def-enum-value-result-code-return: + +return +~~~~~~ + +Value: ``0`` + +.. _gvm-def-enum-value-result-code-user-error: + +user_error +~~~~~~~~~~ + +Value: ``1`` + +.. _gvm-def-enum-value-result-code-vm-error: + +vm_error +~~~~~~~~ + +Value: ``2`` + +.. _gvm-def-enum-value-result-code-internal-error: + +internal_error +~~~~~~~~~~~~~~ + +Value: ``3`` + +.. _gvm-def-enum-storage-type: + +storage_type +------------ + +Type: u8 + +.. _gvm-def-enum-value-storage-type-default: + +default +~~~~~~~ + +Value: ``0`` + +.. _gvm-def-enum-value-storage-type-latest-final: + +latest_final +~~~~~~~~~~~~ + +Value: ``1`` + +.. _gvm-def-enum-value-storage-type-latest-non-final: + +latest_non_final +~~~~~~~~~~~~~~~~ + +Value: ``2`` + +.. _gvm-def-enum-entry-kind: + +entry_kind +---------- + +Type: u8 + +.. _gvm-def-enum-value-entry-kind-main: + +main +~~~~ + +Value: ``0`` + +.. _gvm-def-enum-value-entry-kind-sandbox: + +sandbox +~~~~~~~ + +Value: ``1`` + +.. _gvm-def-enum-value-entry-kind-consensus-stage: + +consensus_stage +~~~~~~~~~~~~~~~ + +Value: ``2`` + +.. _gvm-def-consts-memory-limiter-consts: + +memory_limiter_consts +--------------------- + +Type: u32 + +.. _gvm-def-consts-value-memory-limiter-consts-table-entry: + +table_entry +~~~~~~~~~~~ + +Value: ``64`` + +.. _gvm-def-consts-value-memory-limiter-consts-file-mapping: + +file_mapping +~~~~~~~~~~~~ + +Value: ``256`` + +.. _gvm-def-consts-value-memory-limiter-consts-fd-allocation: + +fd_allocation +~~~~~~~~~~~~~ + +Value: ``96`` + +.. _gvm-def-consts-root-offsets: + +root_offsets +------------ + +Type: u32 + +.. _gvm-def-consts-value-root-offsets-major: + +major +~~~~~ + +Value: ``0`` + +.. _gvm-def-consts-value-root-offsets-contract: + +contract +~~~~~~~~ + +Value: ``1`` + +.. _gvm-def-consts-value-root-offsets-code: + +code +~~~~ + +Value: ``2`` + +.. _gvm-def-consts-value-root-offsets-locked-slots: + +locked_slots +~~~~~~~~~~~~ + +Value: ``3`` + +.. _gvm-def-consts-value-root-offsets-upgraders: + +upgraders +~~~~~~~~~ + +Value: ``4`` + +.. _gvm-def-consts-value-root-offsets-code-slot: + +code_slot +~~~~~~~~~ + +Value: ``5`` + +.. _gvm-def-consts-top-limits: + +top_limits +---------- + +Type: u32 + +.. _gvm-def-consts-value-top-limits-nondet-blocks: + +nondet_blocks +~~~~~~~~~~~~~ + +Value: ``4096`` + +.. _gvm-def-consts-value-top-limits-locked-slots: + +locked_slots +~~~~~~~~~~~~ + +Value: ``256`` + +.. _gvm-def-consts-value-top-limits-upgraders: + +upgraders +~~~~~~~~~ + +Value: ``32`` + +.. _gvm-def-consts-value-top-limits-vm-recursion: + +vm_recursion +~~~~~~~~~~~~ + +Value: ``512`` + +.. _gvm-def-consts-value-top-limits-web-request-min-space: + +web_request_min_space +~~~~~~~~~~~~~~~~~~~~~ + +Value: ``65536`` + +.. _gvm-def-consts-value-top-limits-web-render-min-space: + +web_render_min_space +~~~~~~~~~~~~~~~~~~~~ + +Value: ``134217728`` + +.. _gvm-def-consts-value-top-limits-max-fds: + +max_fds +~~~~~~~ + +Value: ``1024`` + +.. _gvm-def-enum-special-method: + +special_method +-------------- + +Type: str + +.. _gvm-def-enum-value-special-method-get-schema: + +get_schema +~~~~~~~~~~ + +Value: ``#get-schema`` + +.. _gvm-def-enum-value-special-method-errored-message: + +errored_message +~~~~~~~~~~~~~~~ + +Value: ``#error`` + +.. _gvm-def-str-trie-vm-error: + +vm_error +-------- + +Type: str_trie + +.. _gvm-def-str-trie-value-vm-error-timeout: + +``timeout`` +~~~~~~~~~~~ + +.. _gvm-def-str-trie-value-vm-error-absent-leader-nondet-output: + +``absent_leader_nondet_output`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _gvm-def-str-trie-value-vm-error-exit-code: + +``exit_code`` +~~~~~~~~~~~~~ + +Param: i32 + +.. _gvm-def-str-trie-value-vm-error-wasm-trap: + +``wasm_trap`` +~~~~~~~~~~~~~ + +Param: str + +.. _gvm-def-str-trie-value-vm-error-OOM-RAM: + +``OOM RAM`` +~~~~~~~~~~~ + +.. _gvm-def-str-trie-value-vm-error-OOM-RAM-table: + +``OOM RAM table`` +~~~~~~~~~~~~~~~~~ + +.. _gvm-def-str-trie-value-vm-error-OOM-RAM-memory: + +``OOM RAM memory`` +~~~~~~~~~~~~~~~~~~ + +.. _gvm-def-str-trie-value-vm-error-OOM-RAM-limit: + +``OOM RAM limit`` +~~~~~~~~~~~~~~~~~ + +.. _gvm-def-str-trie-value-vm-error-OOM-storage: + +``OOM storage`` +~~~~~~~~~~~~~~~ + +.. _gvm-def-str-trie-value-vm-error-OOM-receipt-nondet-output: + +``OOM receipt nondet_output`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _gvm-def-str-trie-value-vm-error-OOM-receipt-message-internal: + +``OOM receipt message internal`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _gvm-def-str-trie-value-vm-error-OOM-receipt-message-external: + +``OOM receipt message external`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _gvm-def-str-trie-value-vm-error-OOM-fees-internal: + +``OOM fees internal`` +~~~~~~~~~~~~~~~~~~~~~ + +.. _gvm-def-str-trie-value-vm-error-OOM-fees-external: + +``OOM fees external`` +~~~~~~~~~~~~~~~~~~~~~ + +.. _gvm-def-str-trie-value-vm-error-invalid-contract: + +``invalid_contract`` +~~~~~~~~~~~~~~~~~~~~ + +.. _gvm-def-str-trie-value-vm-error-invalid-contract-absent-runner-comment: + +``invalid_contract absent_runner_comment`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _gvm-def-str-trie-value-vm-error-invalid-contract-not-utf8-text: + +``invalid_contract not_utf8_text`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _gvm-def-str-trie-value-vm-error-invalid-contract-malformed-runner: + +``invalid_contract malformed_runner`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _gvm-def-str-trie-value-vm-error-invalid-contract-major-mismatch: + +``invalid_contract major_mismatch`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _gvm-def-str-trie-value-vm-error-invalid-contract-wasm-validating: + +``invalid_contract wasm validating`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _gvm-def-str-trie-value-vm-error-invalid-contract-wasm-linking: + +``invalid_contract wasm linking`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _gvm-def-str-trie-value-vm-error-invalid-contract-wasm-entrypoint: + +``invalid_contract wasm entrypoint`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _gvm-def-str-trie-value-vm-error-host: + +``host`` +~~~~~~~~ + +Param: str + +.. _gvm-def-const-event-max-topics: + +event_max_topics +---------------- + +Type: u32 + +Value: ``4`` diff --git a/executor/crates/sdk-rs/src/abi/consts.rs b/executor/crates/sdk-rs/src/abi/consts.rs index 7cefa1b7f..7d84c7869 100644 --- a/executor/crates/sdk-rs/src/abi/consts.rs +++ b/executor/crates/sdk-rs/src/abi/consts.rs @@ -158,11 +158,11 @@ pub mod memory_limiter_consts { } pub mod root_offsets { - pub const CONTRACT: u32 = 0; - pub const CODE: u32 = 1; - pub const LOCKED_SLOTS: u32 = 2; - pub const UPGRADERS: u32 = 3; - pub const MAJOR: u32 = 4; + pub const MAJOR: u32 = 0; + pub const CONTRACT: u32 = 1; + pub const CODE: u32 = 2; + pub const LOCKED_SLOTS: u32 = 3; + pub const UPGRADERS: u32 = 4; pub const CODE_SLOT: u32 = 5; } diff --git a/runners/genlayer-py-std/src/genlayer/storage/root.py b/runners/genlayer-py-std/src/genlayer/storage/root.py index 4d8323197..63fa0dd2f 100644 --- a/runners/genlayer-py-std/src/genlayer/storage/root.py +++ b/runners/genlayer-py-std/src/genlayer/storage/root.py @@ -26,6 +26,11 @@ class Root: It is set to an actual storage manager in the runtime, but can be overridden for testing purposes. """ + major: u8 + """ + Major version of the GenVM contract expects + """ + contract_instance: Indirection[None] code: Indirection[VLA[u8]] @@ -39,11 +44,6 @@ class Root: """ upgraders: Indirection[VLA[Address]] - major: u8 - """ - Major version of the GenVM contract expects - """ - code_slot: u256 """ Slot id the contract code is stored at, as a raw 32-byte value. If zero (the @@ -74,7 +74,7 @@ def get_vacant_slot(self) -> Slot: This slot can be used to store data without worrying about overwriting contract data. Useful for bootstrapping contract storage """ - return self.slot().indirect(public_abi.root_offsets.MAJOR) + return self.slot().indirect(public_abi.root_offsets.CODE_SLOT) def get_contract_instance[T](self, typ: typing.Type[T], /) -> T: """ diff --git a/runners/genlayer-py-std/src/genlayer/vm/public_abi.py b/runners/genlayer-py-std/src/genlayer/vm/public_abi.py index a47567583..6c29cc2ce 100644 --- a/runners/genlayer-py-std/src/genlayer/vm/public_abi.py +++ b/runners/genlayer-py-std/src/genlayer/vm/public_abi.py @@ -34,11 +34,11 @@ class _MemoryLimiterConsts(typing.NamedTuple): class _RootOffsets(typing.NamedTuple): - CONTRACT: int = 0 - CODE: int = 1 - LOCKED_SLOTS: int = 2 - UPGRADERS: int = 3 - MAJOR: int = 4 + MAJOR: int = 0 + CONTRACT: int = 1 + CODE: int = 2 + LOCKED_SLOTS: int = 3 + UPGRADERS: int = 4 CODE_SLOT: int = 5 root_offsets: typing.Final = _RootOffsets() From 43f0b9f1771b441952fffc281ee137982e455da6 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 20:29:02 +0900 Subject: [PATCH 103/124] =?UTF-8?q?feat(runners):=20optional=20slot/state?= =?UTF-8?q?=20in=20chain=20runner=20id,=20major=20version=20check=20?= =?UTF-8?q?=E2=9C=A8=F0=9F=94=92=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Chain runner ids now accept `chain:` and `chain::` with omitted slot/state defaulting at resolution time. Dependencies with a mismatched major version are rejected before loading code. Introduces `StrSymbol` newtype so runner maps stay interned but lookups accept `&str` without interning untrusted input. --- executor/src/rt/supervisor/actions.rs | 75 ++++++++++++---- executor/src/runners/actions.rs | 1 - executor/src/runners/cache.rs | 59 ++++++++++--- executor/src/runners/mod.rs | 102 ++++++---------------- executor/tests/runner_id.rs | 121 +++++++++++++++++++++++++- 5 files changed, 250 insertions(+), 108 deletions(-) diff --git a/executor/src/rt/supervisor/actions.rs b/executor/src/rt/supervisor/actions.rs index 362a484b3..f2d3fa6f7 100644 --- a/executor/src/rt/supervisor/actions.rs +++ b/executor/src/rt/supervisor/actions.rs @@ -78,7 +78,7 @@ struct Resolved { /// /// Free-standing so it can be shared between contract initialization /// ([`Ctx`]) and runtime `gl_call`s ([`load_runner`]). -fn resolve_runner( +async fn resolve_runner( supervisor: &rt::supervisor::Supervisor, contract_address: calldata::Address, state: public_abi::StorageType, @@ -94,7 +94,7 @@ fn resolve_runner( let resolved: runners::Id = match parsed.resolve(contract_address, state, code_slot) { runners::IdUnresolved::Contract => unreachable!("contract is resolved to chain"), runners::IdUnresolved::Builtin { name, hash } => { - let hash: Bytes32Hash = if hash.as_str() == "test" { + let hash: Bytes32Hash = if hash == "test" { if !supervisor.shared_data.debug_mode.allows_latest_resolution() { log_warn!(":test runner used in non-debug mode, this is not allowed"); return Err(make_malformed_runner_error( @@ -102,39 +102,65 @@ fn resolve_runner( )); } runners::TEST_RUNNER_HASH - } else if hash.as_str() == "latest" { + } else if hash == "latest" { if !supervisor.shared_data.debug_mode.allows_latest_resolution() { log_warn!(":latest runner used in non-debug mode, this is not allowed"); return Err(make_malformed_runner_error( "runner id doesn't match expected format", )); } - let new_latest = supervisor.runner_cache.get_latest(name); - log_info!(runner_id = name.as_str(), new_latest:? = new_latest; "resolving :latest runner"); + let new_latest = supervisor.runner_cache.get_latest(&name); + log_info!(runner_id = name.as_str(); "resolving :latest runner"); let Some(new_latest) = new_latest else { return Err(make_malformed_runner_error( "runner id doesn't match expected format", )); }; - Bytes32Hash::from_gvm32(new_latest.as_str()) + Bytes32Hash::from_gvm32(new_latest) .ok_or_else(|| make_malformed_runner_error("runner hash is not valid gvm32"))? } else { - Bytes32Hash::from_gvm32(hash.as_str()) + Bytes32Hash::from_gvm32(&hash) .ok_or_else(|| make_malformed_runner_error("runner hash is not valid gvm32"))? }; - let hash_sym = symbol_table::GlobalSymbol::from(hash.to_gvm32()); - if !supervisor.runner_cache.has_in_all(name, hash_sym) { - anyhow::bail!("runner {}:{} not found", name, hash_sym); + let hash_gvm32 = hash.to_gvm32(); + if !supervisor.runner_cache.has_in_all(&name, &hash_gvm32) { + anyhow::bail!("runner {}:{} not found", name, hash_gvm32); } - runners::Id::Builtin { name, hash } + runners::Id::Builtin { + name: symbol_table::GlobalSymbol::new(&name), + hash, + } } runners::IdUnresolved::Chain { address, on, slot } => { + let on = on.unwrap_or(public_abi::StorageType::LatestNonFinal); + let slot = match slot { + Some(s) => s, + None => { + let mut storage = rt::vm::storage::Storage::new( + address, + supervisor.get_storage_limiter(), + crate::wasi::genlayer_sdk::StorageHostHolder( + supervisor.host.clone(), + crate::wasi::genlayer_sdk::ReadToken { + account: address, + mode: on, + }, + ), + ); + storage.resolve_code_slot().await.with_context(|| { + format!( + "resolving code slot for chain runner 0x{}", + address.checksum_hex_string() + ) + })? + } + }; runners::Id::Chain { address, on, slot } } runners::IdUnresolved::Custom { hash } => { - let hash = Bytes32Hash::from_gvm32(hash.as_str()).ok_or_else(|| { + let hash = Bytes32Hash::from_gvm32(&hash).ok_or_else(|| { make_malformed_runner_error("custom runner hash is not valid gvm32") })?; runners::Id::Custom { hash } @@ -202,6 +228,22 @@ async fn get_arch( }, ), ); + + let dep_major = storage + .read_major() + .await + .with_context(|| format!("reading major for chain runner {id}"))?; + let node_major = genvm_common::version::CURRENT.major; + if dep_major as u16 != node_major { + return Err(rt::errors::VMError( + public_abi::VmError::invalid_contract().major_mismatch(), + Some(anyhow::anyhow!( + "chain runner {id} major {dep_major} != node major {node_major}" + )), + ) + .into()); + } + let code = storage .read_code_at(slot, limiter) .await @@ -246,7 +288,7 @@ pub(crate) async fn load_runner( symbol_table::GlobalSymbol, sync::DArc, )> { - let resolved = resolve_runner(supervisor, contract_address, state, code_slot, id)?; + let resolved = resolve_runner(supervisor, contract_address, state, code_slot, id).await?; // Custom runners are execution-scoped: a `custom:` is only resolvable // by a scope that registered it (or inherited it from a det parent), so the // shared registry cannot leak a runner across unrelated scopes (e.g. nondet). @@ -355,7 +397,7 @@ pub(crate) async fn map_runner_file( } impl Ctx<'_, '_> { - fn resolve_runner(&self, id: &str) -> anyhow::Result { + async fn resolve_runner(&self, id: &str) -> anyhow::Result { resolve_runner( self.supervisor, self.contract_address, @@ -363,6 +405,7 @@ impl Ctx<'_, '_> { self.code_slot, id, ) + .await } async fn get_arch( @@ -588,7 +631,7 @@ impl Ctx<'_, '_> { runner: uid, action, } => { - let resolved = self.resolve_runner(uid)?; + let resolved = self.resolve_runner(uid).await?; let (uid, new_arch) = self.get_arch(resolved).await?; Box::pin(self.apply(action, uid, &new_arch)) @@ -596,7 +639,7 @@ impl Ctx<'_, '_> { .with_context(|| format!("With {uid}")) } InitAction::Depends(uid) => { - let resolved = self.resolve_runner(uid)?; + let resolved = self.resolve_runner(uid).await?; if !self.visited.insert(resolved.id) { return Ok(None); diff --git a/executor/src/runners/actions.rs b/executor/src/runners/actions.rs index 6065397f9..83221e640 100644 --- a/executor/src/runners/actions.rs +++ b/executor/src/runners/actions.rs @@ -1,4 +1,3 @@ -use genvm_common::*; use std::sync::Arc; #[derive(serde::Serialize, serde::Deserialize, Clone, Copy, PartialEq, Debug)] diff --git a/executor/src/runners/cache.rs b/executor/src/runners/cache.rs index a7430a69c..c516f1ae8 100644 --- a/executor/src/runners/cache.rs +++ b/executor/src/runners/cache.rs @@ -4,12 +4,53 @@ use super::*; use genlayer_sdk::abi; use genvm_common::*; +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] +#[repr(transparent)] +pub struct StrSymbol(symbol_table::GlobalSymbol); + +impl StrSymbol { + pub fn as_str(&self) -> &str { + self.0.as_str() + } +} + +impl std::borrow::Borrow for StrSymbol { + fn borrow(&self) -> &str { + self.0.as_str() + } +} + +impl Ord for StrSymbol { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.as_str().cmp(other.as_str()) + } +} + +impl PartialOrd for StrSymbol { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl serde::Serialize for StrSymbol { + fn serialize(&self, serializer: S) -> Result { + self.0.as_str().serialize(serializer) + } +} + +impl<'de> serde::Deserialize<'de> for StrSymbol { + fn deserialize>(deserializer: D) -> Result { + let s = String::deserialize(deserializer)?; + Ok(Self(symbol_table::GlobalSymbol::from(s))) + } +} + pub struct Reader { cache: sync::CacheMap, runners_data_path: std::path::PathBuf, - all: BTreeMap>, - latest: BTreeMap, + all: BTreeMap>, + latest: BTreeMap, } impl Reader { @@ -48,17 +89,13 @@ impl Reader { }) } - pub fn get_latest(&self, id: symbol_table::GlobalSymbol) -> Option { - self.latest.get(&id).cloned() + pub fn get_latest(&self, id: &str) -> Option<&str> { + self.latest.get(id).map(|s| s.as_str()) } - pub fn has_in_all( - &self, - id: symbol_table::GlobalSymbol, - hash: symbol_table::GlobalSymbol, - ) -> bool { - match self.all.get(&id) { - Some(hashes) => hashes.binary_search(&hash).is_ok(), + pub fn has_in_all(&self, id: &str, hash: &str) -> bool { + match self.all.get(id) { + Some(hashes) => hashes.iter().any(|h| h.as_str() == hash), None => false, } } diff --git a/executor/src/runners/mod.rs b/executor/src/runners/mod.rs index a2f3a1ae5..96e34ea0f 100644 --- a/executor/src/runners/mod.rs +++ b/executor/src/runners/mod.rs @@ -32,20 +32,24 @@ pub fn append_runner_subpath(id: &str, hash: &str, path: &mut std::path::PathBuf /// slot of an arbitrary contract. `address` is a `0x`-prefixed 20 byte hex /// address, `a`/`f` selects accepted (latest non final) / finalized state and /// `slot` is a 32 byte slot id encoded with GVM32 (Crockford Base32). +/// Both `` and `` are optional: `` defaults to `a` and +/// `` defaults to reading the target contract's root slot during +/// resolution (i.e. `chain:
` and `chain:
:a` are valid). /// - `custom:` — a runner registered at runtime, looked up by its hash. +#[derive(Debug)] pub enum IdUnresolved { Builtin { - name: symbol_table::GlobalSymbol, - hash: symbol_table::GlobalSymbol, + name: String, + hash: String, }, Contract, Chain { address: calldata::Address, - on: crate::public_abi::StorageType, - slot: crate::SlotID, + on: Option, + slot: Option, }, Custom { - hash: symbol_table::GlobalSymbol, + hash: String, }, } @@ -80,8 +84,8 @@ impl IdUnresolved { match self { IdUnresolved::Contract => IdUnresolved::Chain { address: contract_address, - on: state, - slot: code_slot, + on: Some(state), + slot: Some(code_slot), }, other => other, } @@ -143,20 +147,25 @@ pub fn parse_runner_id(id: &str) -> Option { if let Some(rest) = id.strip_prefix("chain:") { let mut it = rest.split(':'); let address = it.next()?; - let on = it.next()?; - let slot = it.next()?; + let on_str = it.next(); + let slot_str = it.next(); if it.next().is_some() { return None; } let address = calldata::Address::from(parse_hex_fixed::<20>(address)?); - let on = match on { - "a" => crate::public_abi::StorageType::LatestNonFinal, - "f" => crate::public_abi::StorageType::LatestFinal, + let on = match on_str { + Some("a") | None => Some(crate::public_abi::StorageType::LatestNonFinal), + Some("f") => Some(crate::public_abi::StorageType::LatestFinal), _ => return None, }; - let slot: [u8; 32] = genlayer_sdk::gvm32::decode(slot)?.try_into().ok()?; - let slot = crate::SlotID::from_bytes(slot); + let slot = match slot_str { + Some(s) => { + let bytes: [u8; 32] = genlayer_sdk::gvm32::decode(s)?.try_into().ok()?; + Some(crate::SlotID::from_bytes(bytes)) + } + None => None, + }; return Some(IdUnresolved::Chain { address, on, slot }); } @@ -166,7 +175,7 @@ pub fn parse_runner_id(id: &str) -> Option { return None; } return Some(IdUnresolved::Custom { - hash: symbol_table::GlobalSymbol::new(rest), + hash: rest.to_owned(), }); } @@ -184,8 +193,8 @@ pub fn parse_runner_id(id: &str) -> Option { return None; } Some(IdUnresolved::Builtin { - name: symbol_table::GlobalSymbol::new(name), - hash: symbol_table::GlobalSymbol::new(hash), + name: name.to_owned(), + hash: hash.to_owned(), }) } @@ -303,62 +312,3 @@ pub fn verify_runner(runner_id: &str) -> Option<(&str, &str)> { } Some((runner_id, runner_hash)) } - -#[cfg(test)] -mod tests { - use super::*; - - fn addr40() -> String { - format!("0x{}1", "0".repeat(39)) - } - fn slot64() -> String { - genlayer_sdk::gvm32::encode(&[0x11u8; 32]) - } - - #[test] - fn parse_runner_id_forms() { - assert!(matches!( - parse_runner_id("contract"), - Some(IdUnresolved::Contract) - )); - assert!(matches!( - parse_runner_id("py-genlayer:test"), - Some(IdUnresolved::Builtin { .. }) - )); - assert!(matches!( - parse_runner_id("custom:deadbeef"), - Some(IdUnresolved::Custom { .. }) - )); - - match parse_runner_id(&format!("chain:{}:f:{}", addr40(), slot64())) { - Some(IdUnresolved::Chain { on, .. }) => { - assert_eq!(on, crate::public_abi::StorageType::LatestFinal) - } - _ => panic!("expected a chain runner id"), - } - match parse_runner_id(&format!("chain:{}:a:{}", addr40(), slot64())) { - Some(IdUnresolved::Chain { on, .. }) => { - assert_eq!(on, crate::public_abi::StorageType::LatestNonFinal) - } - _ => panic!("expected a chain runner id"), - } - } - - #[test] - fn parse_runner_id_rejects_malformed() { - assert!(parse_runner_id("custom:").is_none()); // empty hash - assert!(parse_runner_id("custom:bad/char").is_none()); // invalid char - assert!(parse_runner_id(":hash").is_none()); // empty name - assert!(parse_runner_id("name:").is_none()); // empty hash - assert!(parse_runner_id("with space:hash").is_none()); // invalid name char - - // chain: closed grammar - assert!(parse_runner_id(&format!("chain:0x01:f:{}", slot64())).is_none()); // short address - assert!(parse_runner_id(&format!("chain:{}:f:{}", "0".repeat(40), slot64())).is_none()); // missing 0x - assert!(parse_runner_id(&format!("chain:{}:f:0x02", addr40())).is_none()); // short slot - assert!(parse_runner_id(&format!("chain:{}:x:{}", addr40(), slot64())).is_none()); // bad a|f - assert!(parse_runner_id(&format!("chain:{}:f:{}:extra", addr40(), slot64())).is_none()); // extra segment - assert!(parse_runner_id(&format!("chain:0x{}:f:{}", "z".repeat(40), slot64())).is_none()); - // non-hex address - } -} diff --git a/executor/tests/runner_id.rs b/executor/tests/runner_id.rs index 2c5fcf715..bec277f80 100644 --- a/executor/tests/runner_id.rs +++ b/executor/tests/runner_id.rs @@ -1,11 +1,18 @@ use genvm::calldata::Address; use genvm::public_abi::StorageType; -use genvm::runners::Id; +use genvm::runners::{self, Id, IdUnresolved}; use genvm::SlotID; +fn test_addr() -> String { + format!("0x{}1", "0".repeat(39)) +} + +fn test_slot() -> String { + genlayer_sdk::gvm32::encode(&[0x11u8; 32]) +} + #[test] fn chain_canonical_uses_checksum_address() { - // EIP-55 address whose checksum form has mixed case let address = Address::from([ 0x5a, 0xae, 0xb6, 0x05, 0x3f, 0x3e, 0x94, 0xc9, 0xb9, 0xa0, 0x9f, 0x33, 0x66, 0x94, 0x35, 0xe7, 0xef, 0x1b, 0xea, 0xed, @@ -20,9 +27,115 @@ fn chain_canonical_uses_checksum_address() { let expected = format!( "chain:0x{}:a:{}", std::str::from_utf8(&address.checksum_hex()).unwrap(), - "0".repeat(52), // gvm32 of 32 zero bytes + "0".repeat(52), ); assert_eq!(id.canonical().as_str(), expected.as_str()); - // sanity: the address part is genuinely mixed-case (checksummed), not lowercase assert!(expected.contains("5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed")); } + +#[test] +fn parse_runner_id_forms() { + assert!(matches!( + runners::parse_runner_id("contract"), + Some(IdUnresolved::Contract) + )); + assert!(matches!( + runners::parse_runner_id("py-genlayer:test"), + Some(IdUnresolved::Builtin { .. }) + )); + assert!(matches!( + runners::parse_runner_id("custom:deadbeef"), + Some(IdUnresolved::Custom { .. }) + )); + + match runners::parse_runner_id(&format!("chain:{}:f:{}", test_addr(), test_slot())) { + Some(IdUnresolved::Chain { on, slot, .. }) => { + assert_eq!(on, Some(StorageType::LatestFinal)); + assert!(slot.is_some()); + } + other => panic!("expected Chain, got {other:?}"), + } + match runners::parse_runner_id(&format!("chain:{}:a:{}", test_addr(), test_slot())) { + Some(IdUnresolved::Chain { on, slot, .. }) => { + assert_eq!(on, Some(StorageType::LatestNonFinal)); + assert!(slot.is_some()); + } + other => panic!("expected Chain, got {other:?}"), + } +} + +#[test] +fn parse_runner_id_rejects_malformed() { + assert!(runners::parse_runner_id("custom:").is_none()); + assert!(runners::parse_runner_id("custom:bad/char").is_none()); + assert!(runners::parse_runner_id(":hash").is_none()); + assert!(runners::parse_runner_id("name:").is_none()); + assert!(runners::parse_runner_id("with space:hash").is_none()); + + assert!(runners::parse_runner_id(&format!("chain:0x01:f:{}", test_slot())).is_none()); + assert!( + runners::parse_runner_id(&format!("chain:{}:f:{}", "0".repeat(40), test_slot())).is_none() + ); + assert!(runners::parse_runner_id(&format!("chain:{}:f:0x02", test_addr())).is_none()); + assert!( + runners::parse_runner_id(&format!("chain:{}:x:{}", test_addr(), test_slot())).is_none() + ); + assert!( + runners::parse_runner_id(&format!("chain:{}:f:{}:extra", test_addr(), test_slot())) + .is_none() + ); + assert!( + runners::parse_runner_id(&format!("chain:0x{}:f:{}", "z".repeat(40), test_slot())) + .is_none() + ); +} + +#[test] +fn chain_without_slot_id() { + match runners::parse_runner_id(&format!("chain:{}:a", test_addr())) { + Some(IdUnresolved::Chain { on, slot, .. }) => { + assert_eq!(on, Some(StorageType::LatestNonFinal)); + assert!(slot.is_none(), "slot must be None when omitted"); + } + other => panic!("expected Chain, got {other:?}"), + } +} + +#[test] +fn chain_without_on_or_slot() { + match runners::parse_runner_id(&format!("chain:{}", test_addr())) { + Some(IdUnresolved::Chain { on, slot, .. }) => { + assert_eq!(on, Some(StorageType::LatestNonFinal)); + assert!(slot.is_none(), "slot must be None when omitted"); + } + other => panic!("expected Chain, got {other:?}"), + } +} + +#[test] +fn chain_with_explicit_slot() { + match runners::parse_runner_id(&format!("chain:{}:f:{}", test_addr(), test_slot())) { + Some(IdUnresolved::Chain { on, slot, .. }) => { + assert_eq!(on, Some(StorageType::LatestFinal)); + assert!(slot.is_some(), "slot must be Some when given"); + } + other => panic!("expected Chain, got {other:?}"), + } +} + +#[test] +fn chain_resolve_fills_contract_fields() { + let parsed = runners::parse_runner_id(&format!("chain:{}", test_addr())).unwrap(); + let contract_addr = Address::from([0xAA; 20]); + let state = StorageType::LatestFinal; + let code_slot = SlotID::from_bytes([0xBB; 32]); + let resolved = parsed.resolve(contract_addr, state, code_slot); + match resolved { + IdUnresolved::Chain { on, slot, address } => { + assert_ne!(address, contract_addr, "chain: keeps its own address"); + assert_eq!(on, Some(StorageType::LatestNonFinal)); + assert!(slot.is_none(), "chain: slot is not filled by resolve"); + } + _ => panic!("expected Chain"), + } +} From 250c234e89592bad59bd55d9122b7538edbff435 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 20:29:07 +0900 Subject: [PATCH 104/124] =?UTF-8?q?fix(executor):=20stricter=20version=20s?= =?UTF-8?q?tring=20validation=20in=20current=5Fversion=20=F0=9F=94=92?= =?UTF-8?q?=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/crates/common/src/version.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/executor/crates/common/src/version.rs b/executor/crates/common/src/version.rs index d3c2b02b1..c344f56b7 100644 --- a/executor/crates/common/src/version.rs +++ b/executor/crates/common/src/version.rs @@ -134,10 +134,13 @@ const fn current_version() -> Version { if !ok_minor || i >= id.len() || id[i] != b'.' { panic!("invalid VERSION: missing minor"); } - let (patch, _, ok_patch) = parse_u16(id, i + 1); // skip '.' + let (patch, i, ok_patch) = parse_u16(id, i + 1); // skip '.' if !ok_patch { panic!("invalid VERSION: missing patch"); } + if i < id.len() && id[i] != b'-' && id[i] != b'\n' { + panic!("invalid VERSION: unexpected character after patch"); + } Version { major, minor, From bbf7fc139595870fa4416e4cddbf3be1120b270f Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Tue, 23 Jun 2026 20:29:13 +0900 Subject: [PATCH 105/124] =?UTF-8?q?fix(tests):=20use=20print(e)=20in=20reg?= =?UTF-8?q?ister=5Fno=5Fperm=20test=20=F0=9F=90=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/cases/stable/runners/register_no_perm.0.stdout | 2 +- tests/cases/stable/runners/register_no_perm.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/cases/stable/runners/register_no_perm.0.stdout b/tests/cases/stable/runners/register_no_perm.0.stdout index e26bb8a09..31d88ed50 100644 --- a/tests/cases/stable/runners/register_no_perm.0.stdout +++ b/tests/cases/stable/runners/register_no_perm.0.stdout @@ -1,2 +1,2 @@ -forbidden: SystemError +6: forbidden executed with `Return(null)` diff --git a/tests/cases/stable/runners/register_no_perm.py b/tests/cases/stable/runners/register_no_perm.py index 67dbb51c2..8e3d1cd64 100644 --- a/tests/cases/stable/runners/register_no_perm.py +++ b/tests/cases/stable/runners/register_no_perm.py @@ -6,5 +6,5 @@ register_runner(b'# { "Depends": "py-genlayer:test" }\nx\n') print('registered') except Exception as e: - print(f'forbidden: {type(e).__name__}') + print(e) exit(0) From 4feba85b65fdb3e9f732827263e489b92c185407 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Wed, 24 Jun 2026 19:08:49 +0900 Subject: [PATCH 106/124] =?UTF-8?q?chore(tests):=20fix=20tests=20=E2=9C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/crates/common/src/bytes32.rs | 45 +++- executor/crates/common/tests/bytes32.rs | 32 ++- executor/crates/sdk-rs/Cargo.lock | 1 + executor/crates/sdk-rs/src/gvm32.rs | 41 +++- executor/crates/sdk-rs/src/storage/array.rs | 4 + executor/crates/sdk-rs/src/storage/mod.rs | 21 +- executor/crates/sdk-rs/tests/gvm32.rs | 8 +- executor/src/rt/errors.rs | 19 +- executor/src/rt/mod.rs | 4 + executor/src/rt/supervisor/actions.rs | 52 +++-- executor/src/rt/vm/storage.rs | 8 +- executor/src/runners/mod.rs | 2 +- modules/implementation/src/common/mod.rs | 2 +- modules/implementation/src/llm/merge.rs | 172 -------------- modules/implementation/src/manager/modules.rs | 49 ++-- .../implementation/src/scripting/ctx/req.rs | 91 -------- .../src/scripting/ctx/signing.rs | 60 ----- modules/implementation/src/scripting/mod.rs | 1 + modules/implementation/tests/merge.rs | 169 ++++++++++++++ .../tests/request_body_limit.rs | 88 ++++++++ .../implementation/tests/signing_server.rs | 60 +++++ modules/interfaces/Cargo.lock | 1 + .../genlayer/_internal/on_chain/storage.py | 5 +- .../src/genlayer/storage/core.py | 21 +- .../src/genlayer/storage/root.py | 11 + .../src/genlayer/vm/__init__.py | 6 +- runners/support/default.nix | 2 +- runners/support/gvm32.nix | 17 +- runners/support/versions/current.nix | 27 ++- runners/support/versions/dev-mode.nix | 2 +- runners/support/versions/generation-00.nix | 48 +--- runners/support/versions/hash-updater.py | 212 ++++++++++++++++++ tests/cases/_hello_world_.0.hash | 1 - tests/cases/_hello_world_class.0.hash | 1 - tests/cases/_hello_world_class.0_0.hash | 1 - tests/cases/_hello_world_class_nondet.0.hash | 1 - .../semi-stable/llm/issue_288_compat.0.stdout | 4 - .../semi-stable/llm/issue_288_compat.jsonnet | 6 - .../cases/semi-stable/llm/issue_288_compat.py | 51 ----- .../semi-stable/llm/percent_in_prompt.0.hash | 1 - tests/cases/semi-stable/llm/woc.0.hash | 1 - tests/cases/semi-stable/llm/woc.0_0.hash | 1 - tests/cases/semi-stable/llm/woc.0_0_0_0.hash | 1 - .../web/file_schema_web_bash.0.hash | 1 - .../web/file_schema_web_proc.0.hash | 1 - .../semi-stable/web/request_signed.0.hash | 1 - .../wasi/environ_args/environ_args.0.hash | 1 - .../wasi/hash_random/hash_random.0.hash | 1 - .../agentic/wasi/set_order/set_order.0.hash | 1 - .../agentic/wasi/wasi_clock/wasi_clock.0.hash | 1 - .../wasi/wasi_random/wasi_random.0.hash | 1 - .../stable/exploits/call_wasi_extra.0.hash | 1 - tests/cases/stable/exploits/close_std.0.hash | 1 - .../stable/exploits/deep_calldata.0.hash | 1 - .../exploits/disagree_in_sandbox.0.hash | 1 - tests/cases/stable/exploits/flt.0.hash | 1 - tests/cases/stable/exploits/fork_bomb.0.hash | 1 - .../cases/stable/exploits/method_init.0.hash | 1 - .../stable/exploits/method_init.0_0.hash | 1 - .../stable/exploits/method_private.0.hash | 1 - .../stable/exploits/method_private.0_0.hash | 1 - tests/cases/stable/exploits/oom.0.hash | 1 - tests/cases/stable/exploits/rec.0.hash | 1 - tests/cases/stable/exploits/rec_1023.0.hash | 1 - tests/cases/stable/exploits/rec_1024.0.hash | 1 - .../stable/exploits/storage_page_limit.0.hash | 1 - .../exploits/storage_page_limit.0_0.hash | 1 - .../exploits/storage_page_limit.0_1.hash | 1 - .../stable/exploits/storage_rw_long.0.hash | 1 - .../stable/exploits/storage_rw_long.0_0.hash | 1 - .../subtract_on_start_underflow.0.hash | 1 - .../cases/stable/exploits/unreachable.0.hash | 1 - .../leader_errors/empty_leader_result.0.hash | 1 - .../empty_leader_result.0_0.hash | 1 - .../leader_errors/leader_no_nondet.0.hash | 1 - .../leader_errors/leader_no_nondet.0_0.hash | 1 - .../nondet/leader_errors/simple_leader.0.hash | 1 - .../leader_errors/simple_leader.0_0.hash | 1 - .../leader_errors/simple_valid_err_err.0.hash | 1 - .../simple_valid_err_err.0_0.hash | 1 - .../simple_valid_err_exit.0.hash | 1 - .../simple_valid_err_exit.0_0.hash | 1 - .../simple_valid_err_exit_wrong_err.0.hash | 1 - .../simple_valid_err_exit_wrong_err.0_0.hash | 1 - .../simple_valid_err_nerr.0.hash | 1 - .../simple_valid_err_nerr.0_0.hash | 1 - .../nondet/metod_det_get_webpage.0.hash | 1 - .../nondet/metod_det_get_webpage.0_0.hash | 1 - tests/cases/stable/nondet/trivial.0.hash | 1 - tests/cases/stable/nondet/trivial.0_0.hash | 1 - .../nondet/validator/rollback_agree.0.hash | 1 - .../nondet/validator/rollback_agree.0_0.hash | 1 - .../nondet/validator/rollback_disagree.0.hash | 1 - .../validator/rollback_disagree.0_0.hash | 1 - .../nondet/validator/rollback_imm.0.hash | 1 - .../nondet/validator/rollback_imm.0_0.hash | 1 - .../nondet/validator/rollback_imm.0_1.hash | 1 - .../nondet/validator/rollback_imm.0_2.hash | 1 - .../cases/stable/nondet/validator/sync.0.hash | 1 - .../stable/nondet/validator/sync.0_0.hash | 1 - .../stable/nondet/validator/sync_err.0.hash | 1 - .../stable/nondet/validator/sync_err.0_0.hash | 1 - tests/cases/stable/py/balances/balance.0.hash | 1 - .../stable/py/balances/balance_eth.0.hash | 1 - .../py/balances/sandbox_overspend.0.hash | 1 - .../py/balances/sandbox_overspend_2.0.hash | 1 - .../stable/py/balances/undefined_all.0.hash | 1 - .../stable/py/balances/undefined_all.0_0.hash | 1 - .../py/balances/undefined_all.0_0_0.hash | 1 - .../py/balances/undefined_method.0.hash | 1 - .../py/balances/undefined_method.0_0.hash | 1 - .../py/balances/undefined_method.0_0_0.hash | 1 - .../balances/undefined_method_payable.0.hash | 1 - .../undefined_method_payable.0_0.hash | 1 - .../undefined_method_payable.0_0_0.hash | 1 - .../py/balances/undefined_receive.0.hash | 1 - .../py/balances/undefined_receive.0_0.hash | 1 - .../py/balances/undefined_receive.0_0_0.hash | 1 - .../cases/stable/py/embeddings/simple.0.hash | 1 - .../stable/py/embeddings/simple.0_0.hash | 1 - .../stable/py/embeddings/simple_det.0.hash | 1 - .../stable/py/embeddings/simple_det.0_0.hash | 1 - .../py/embeddings/simple_tokenizer.0.hash | 1 - .../py/embeddings/simple_tokenizer.0_0.hash | 1 - tests/cases/stable/py/embeddings/vecdb.0.hash | 1 - .../cases/stable/py/events/post_event.0.hash | 1 - .../stable/py/intercontract/call_view.0.hash | 1 - .../py/intercontract/call_view.0_0.hash | 1 - .../py/intercontract/call_view.0_0_0.hash | 1 - .../py/intercontract/call_view_iface.0.hash | 1 - .../py/intercontract/call_view_iface.0_0.hash | 1 - .../intercontract/call_view_iface.0_0_0.hash | 1 - .../stable/py/intercontract/deploy.0.hash | 1 - .../py/intercontract/deploy_salt.0.hash | 1 - .../py/intercontract/eth_call_view.0.hash | 1 - .../py/intercontract/send_message.0.hash | 1 - .../py/intercontract/send_message_eth.0.hash | 1 - .../py/intercontract/send_message_on.0.hash | 1 - .../py/intercontract/send_message_on.0_0.hash | 1 - .../intercontract/send_message_on.0_0_0.hash | 1 - .../stable/py/other/meth/method_init.0.hash | 1 - .../other/meth/method_init_wrong_name.0.hash | 1 - .../stable/py/other/meth/method_public.0.hash | 1 - .../py/other/meth/method_public.0_0.hash | 1 - .../stable/py/other/meth/method_retn.0.hash | 1 - .../stable/py/other/meth/method_retn.0_0.hash | 1 - .../py/other/meth/method_retn_view.0.hash | 1 - .../py/other/meth/method_retn_view.0_0.hash | 1 - .../py/other/meth/method_rollback.0.hash | 1 - .../py/other/meth/method_rollback.0_0.hash | 1 - .../cases/stable/py/other/ret/returns.0.hash | 1 - .../stable/py/other/ret/returns.0_0.hash | 1 - .../cases/stable/py/other/ret/returns.1.hash | 1 - .../stable/py/other/ret/returns.1_0.hash | 1 - .../cases/stable/py/other/ret/returns.2.hash | 1 - .../stable/py/other/ret/returns.2_0.hash | 1 - .../cases/stable/py/other/ret/returns.3.hash | 1 - .../stable/py/other/ret/returns.3_0.hash | 1 - .../cases/stable/py/other/ret/returns.4.hash | 1 - .../stable/py/other/ret/returns.4_0.hash | 1 - .../cases/stable/py/other/ret/returns.5.hash | 1 - .../stable/py/other/ret/returns.5_0.hash | 1 - .../cases/stable/py/other/ret/returns.6.hash | 1 - .../stable/py/other/ret/returns.6_0.hash | 1 - .../cases/stable/py/other/ret/returns.7.hash | 1 - .../stable/py/other/ret/returns.7_0.hash | 1 - .../cases/stable/py/other/ret/returns.8.hash | 1 - .../stable/py/other/ret/returns.8_0.hash | 1 - .../cases/stable/py/other/ret/returns.9.hash | 1 - .../stable/py/other/ret/returns.9_0.hash | 1 - .../stable/py/pitfalls/multi_contract.0.hash | 1 - .../cases/stable/py/pitfalls/pub_ctor.0.hash | 1 - .../stable/py/pitfalls/store_proxy.0.hash | 1 - .../stable/py/rollbacks/call_view.0.hash | 1 - .../stable/py/rollbacks/call_view.0_0.hash | 1 - .../stable/py/rollbacks/call_view.0_0_0.hash | 1 - .../py/rollbacks/calldata_rollback.0.hash | 1 - .../py/rollbacks/calldata_rollback.0_0.hash | 1 - .../py/rollbacks/calldata_rollback.0_0_0.hash | 1 - tests/cases/stable/py/rollbacks/nondet.0.hash | 1 - tests/cases/stable/py/rollbacks/simple.0.hash | 1 - .../py/sandbox/det/s/assign-json.0.hash | 1 - .../py/sandbox/det/s/assign-json.0_0.hash | 1 - .../cases/stable/py/sandbox/det/s/exit.0.hash | 1 - .../stable/py/sandbox/det/s/exit.0_0.hash | 1 - .../stable/py/sandbox/det/s/print.0.hash | 1 - .../stable/py/sandbox/det/s/print.0_0.hash | 1 - .../stable/py/sandbox/det/s/rollback.0.hash | 1 - .../stable/py/sandbox/det/s/rollback.0_0.hash | 1 - .../stable/py/sandbox/det/s/sandbox.0.hash | 1 - .../stable/py/sandbox/det/s/sandbox.0_0.hash | 1 - .../py/sandbox/det/sandbox_write.0.hash | 1 - .../py/sandbox/non-det/s/assign-json.0.hash | 1 - .../py/sandbox/non-det/s/assign-json.0_0.hash | 1 - .../stable/py/sandbox/non-det/s/exit.0.hash | 1 - .../stable/py/sandbox/non-det/s/exit.0_0.hash | 1 - .../stable/py/sandbox/non-det/s/print.0.hash | 1 - .../py/sandbox/non-det/s/print.0_0.hash | 1 - .../py/sandbox/non-det/s/rollback.0.hash | 1 - .../py/sandbox/non-det/s/rollback.0_0.hash | 1 - .../stable/py/schemas/complex_types.0.hash | 1 - .../stable/py/schemas/complex_types.0_0.hash | 1 - .../cases/stable/py/schemas/prim_types.0.hash | 1 - .../stable/py/schemas/prim_types.0_0.hash | 1 - .../cases/stable/py/schemas/ret-float.0.hash | 1 - .../stable/py/schemas/ret-float.0_0.hash | 1 - .../cases/stable/py/schemas/ret-tuple.0.hash | 1 - .../stable/py/schemas/ret-tuple.0_0.hash | 1 - tests/cases/stable/py/schemas/ret.0.hash | 1 - tests/cases/stable/py/schemas/ret.0_0.hash | 1 - tests/cases/stable/py/schemas/trivial.0.hash | 1 - .../cases/stable/py/schemas/trivial.0_0.hash | 1 - .../stable/runners/dup-dependency.0.hash | 1 - .../cases/stable/runners/env-template.0.hash | 1 - .../stable/runners/malformed_runner.0.hash | 1 - tests/cases/stable/runners/no_runner.0.hash | 1 - tests/cases/stable/runners/zip/no-zip.0.hash | 1 - tests/cases/stable/self-run/datetime.0.hash | 1 - tests/cases/stable/self-run/floats.0.hash | 1 - tests/cases/stable/self-run/formats.0.hash | 1 - tests/cases/stable/self-run/issue_163.0.hash | 1 - tests/cases/stable/self-run/module/np.0.hash | 1 - tests/cases/stable/self-run/module/pil.0.hash | 1 - tests/cases/stable/self-run/re.0.hash | 1 - .../cases/stable/self-run/typing_is_ok.0.hash | 1 - .../cases/stable/storage/alloc_generic.0.hash | 1 - .../stable/storage/alloc_generic_err.0.hash | 1 - tests/cases/stable/storage/base.0.hash | 1 - .../cases/stable/storage/bootstrapper.0.hash | 1 - .../stable/storage/bootstrapper.0_0.hash | 1 - .../stable/storage/bootstrapper.0_0_0.hash | 1 - .../stable/storage/bootstrapper.0_0_0_0.hash | 1 - .../storage/bootstrapper.0_0_0_0_0.hash | 1 - .../storage/bootstrapper.0_0_0_0_0_0.hash | 1 - .../cases/stable/storage/bootstrapper.jsonnet | 4 +- tests/cases/stable/storage/floats.0.hash | 1 - tests/cases/stable/storage/gvm-89.0.hash | 1 - tests/cases/stable/storage/gvm-89.0_0.hash | 1 - .../storage/locking/default-frozen.0.hash | 1 - .../storage/locking/default-frozen.0.stdout | 2 +- .../storage/locking/default-frozen.0_0.hash | 1 - .../storage/locking/default-frozen.0_0.stdout | 2 +- .../storage/locking/default-frozen.0_0_0.hash | 1 - .../stable/storage/locking/modify_ctor.0.hash | 1 - .../storage/locking/modify_ctor.0.stdout | 4 +- .../storage/locking/modify_ctor.0_0.hash | 1 - .../storage/locking/modify_later.0.hash | 1 - .../storage/locking/modify_later.0.stdout | 2 +- .../storage/locking/modify_later.0_0.hash | 1 - .../storage/locking/modify_later.0_0.stdout | 2 +- .../storage/locking/modify_later.0_0_0.hash | 1 - tests/cases/stable/storage/np.0.hash | 1 - tests/cases/stable/storage/persists.0.hash | 1 - tests/cases/stable/storage/persists.0_0.hash | 1 - tests/cases/stable/storage/read_nondet.0.hash | 1 - .../stable/storage/storage_tree_map.0.hash | 1 - tests/cases/stable/storage/to_str.0.hash | 1 - .../stable/storage/tree_map_nested.0.hash | 1 - ...eq_prompt_non_comparative_validator.0.hash | 1 - ...rompt_non_comparative_validator_bad.0.hash | 1 - .../unstable/nondet/validator/agree.0.hash | 1 - .../unstable/nondet/validator/agree.0_0.hash | 1 - .../unstable/nondet/validator/disagree.0.hash | 1 - .../nondet/validator/disagree.0_0.hash | 1 - .../nondet/web/get_webpage_html.0.hash | 1 - .../nondet/web/get_webpage_screenshot.0.hash | 1 - .../nondet/web/get_webpage_text.0.hash | 1 - .../cases/unstable/nondet/web/sandbox.0.hash | 1 - .../ya_test_runner_plugins/integration.py | 14 +- 269 files changed, 836 insertions(+), 763 deletions(-) create mode 100644 modules/implementation/tests/merge.rs create mode 100644 modules/implementation/tests/request_body_limit.rs create mode 100644 modules/implementation/tests/signing_server.rs create mode 100755 runners/support/versions/hash-updater.py delete mode 100644 tests/cases/_hello_world_.0.hash delete mode 100644 tests/cases/_hello_world_class.0.hash delete mode 100644 tests/cases/_hello_world_class.0_0.hash delete mode 100644 tests/cases/_hello_world_class_nondet.0.hash delete mode 100644 tests/cases/semi-stable/llm/issue_288_compat.0.stdout delete mode 100644 tests/cases/semi-stable/llm/issue_288_compat.jsonnet delete mode 100644 tests/cases/semi-stable/llm/issue_288_compat.py delete mode 100644 tests/cases/semi-stable/llm/percent_in_prompt.0.hash delete mode 100644 tests/cases/semi-stable/llm/woc.0.hash delete mode 100644 tests/cases/semi-stable/llm/woc.0_0.hash delete mode 100644 tests/cases/semi-stable/llm/woc.0_0_0_0.hash delete mode 100644 tests/cases/semi-stable/web/file_schema_web_bash.0.hash delete mode 100644 tests/cases/semi-stable/web/file_schema_web_proc.0.hash delete mode 100644 tests/cases/semi-stable/web/request_signed.0.hash delete mode 100644 tests/cases/stable/agentic/wasi/environ_args/environ_args.0.hash delete mode 100644 tests/cases/stable/agentic/wasi/hash_random/hash_random.0.hash delete mode 100644 tests/cases/stable/agentic/wasi/set_order/set_order.0.hash delete mode 100644 tests/cases/stable/agentic/wasi/wasi_clock/wasi_clock.0.hash delete mode 100644 tests/cases/stable/agentic/wasi/wasi_random/wasi_random.0.hash delete mode 100644 tests/cases/stable/exploits/call_wasi_extra.0.hash delete mode 100644 tests/cases/stable/exploits/close_std.0.hash delete mode 100644 tests/cases/stable/exploits/deep_calldata.0.hash delete mode 100644 tests/cases/stable/exploits/disagree_in_sandbox.0.hash delete mode 100644 tests/cases/stable/exploits/flt.0.hash delete mode 100644 tests/cases/stable/exploits/fork_bomb.0.hash delete mode 100644 tests/cases/stable/exploits/method_init.0.hash delete mode 100644 tests/cases/stable/exploits/method_init.0_0.hash delete mode 100644 tests/cases/stable/exploits/method_private.0.hash delete mode 100644 tests/cases/stable/exploits/method_private.0_0.hash delete mode 100644 tests/cases/stable/exploits/oom.0.hash delete mode 100644 tests/cases/stable/exploits/rec.0.hash delete mode 100644 tests/cases/stable/exploits/rec_1023.0.hash delete mode 100644 tests/cases/stable/exploits/rec_1024.0.hash delete mode 100644 tests/cases/stable/exploits/storage_page_limit.0.hash delete mode 100644 tests/cases/stable/exploits/storage_page_limit.0_0.hash delete mode 100644 tests/cases/stable/exploits/storage_page_limit.0_1.hash delete mode 100644 tests/cases/stable/exploits/storage_rw_long.0.hash delete mode 100644 tests/cases/stable/exploits/storage_rw_long.0_0.hash delete mode 100644 tests/cases/stable/exploits/subtract_on_start_underflow.0.hash delete mode 100644 tests/cases/stable/exploits/unreachable.0.hash delete mode 100644 tests/cases/stable/nondet/leader_errors/empty_leader_result.0.hash delete mode 100644 tests/cases/stable/nondet/leader_errors/empty_leader_result.0_0.hash delete mode 100644 tests/cases/stable/nondet/leader_errors/leader_no_nondet.0.hash delete mode 100644 tests/cases/stable/nondet/leader_errors/leader_no_nondet.0_0.hash delete mode 100644 tests/cases/stable/nondet/leader_errors/simple_leader.0.hash delete mode 100644 tests/cases/stable/nondet/leader_errors/simple_leader.0_0.hash delete mode 100644 tests/cases/stable/nondet/leader_errors/simple_valid_err_err.0.hash delete mode 100644 tests/cases/stable/nondet/leader_errors/simple_valid_err_err.0_0.hash delete mode 100644 tests/cases/stable/nondet/leader_errors/simple_valid_err_exit.0.hash delete mode 100644 tests/cases/stable/nondet/leader_errors/simple_valid_err_exit.0_0.hash delete mode 100644 tests/cases/stable/nondet/leader_errors/simple_valid_err_exit_wrong_err.0.hash delete mode 100644 tests/cases/stable/nondet/leader_errors/simple_valid_err_exit_wrong_err.0_0.hash delete mode 100644 tests/cases/stable/nondet/leader_errors/simple_valid_err_nerr.0.hash delete mode 100644 tests/cases/stable/nondet/leader_errors/simple_valid_err_nerr.0_0.hash delete mode 100644 tests/cases/stable/nondet/metod_det_get_webpage.0.hash delete mode 100644 tests/cases/stable/nondet/metod_det_get_webpage.0_0.hash delete mode 100644 tests/cases/stable/nondet/trivial.0.hash delete mode 100644 tests/cases/stable/nondet/trivial.0_0.hash delete mode 100644 tests/cases/stable/nondet/validator/rollback_agree.0.hash delete mode 100644 tests/cases/stable/nondet/validator/rollback_agree.0_0.hash delete mode 100644 tests/cases/stable/nondet/validator/rollback_disagree.0.hash delete mode 100644 tests/cases/stable/nondet/validator/rollback_disagree.0_0.hash delete mode 100644 tests/cases/stable/nondet/validator/rollback_imm.0.hash delete mode 100644 tests/cases/stable/nondet/validator/rollback_imm.0_0.hash delete mode 100644 tests/cases/stable/nondet/validator/rollback_imm.0_1.hash delete mode 100644 tests/cases/stable/nondet/validator/rollback_imm.0_2.hash delete mode 100644 tests/cases/stable/nondet/validator/sync.0.hash delete mode 100644 tests/cases/stable/nondet/validator/sync.0_0.hash delete mode 100644 tests/cases/stable/nondet/validator/sync_err.0.hash delete mode 100644 tests/cases/stable/nondet/validator/sync_err.0_0.hash delete mode 100644 tests/cases/stable/py/balances/balance.0.hash delete mode 100644 tests/cases/stable/py/balances/balance_eth.0.hash delete mode 100644 tests/cases/stable/py/balances/sandbox_overspend.0.hash delete mode 100644 tests/cases/stable/py/balances/sandbox_overspend_2.0.hash delete mode 100644 tests/cases/stable/py/balances/undefined_all.0.hash delete mode 100644 tests/cases/stable/py/balances/undefined_all.0_0.hash delete mode 100644 tests/cases/stable/py/balances/undefined_all.0_0_0.hash delete mode 100644 tests/cases/stable/py/balances/undefined_method.0.hash delete mode 100644 tests/cases/stable/py/balances/undefined_method.0_0.hash delete mode 100644 tests/cases/stable/py/balances/undefined_method.0_0_0.hash delete mode 100644 tests/cases/stable/py/balances/undefined_method_payable.0.hash delete mode 100644 tests/cases/stable/py/balances/undefined_method_payable.0_0.hash delete mode 100644 tests/cases/stable/py/balances/undefined_method_payable.0_0_0.hash delete mode 100644 tests/cases/stable/py/balances/undefined_receive.0.hash delete mode 100644 tests/cases/stable/py/balances/undefined_receive.0_0.hash delete mode 100644 tests/cases/stable/py/balances/undefined_receive.0_0_0.hash delete mode 100644 tests/cases/stable/py/embeddings/simple.0.hash delete mode 100644 tests/cases/stable/py/embeddings/simple.0_0.hash delete mode 100644 tests/cases/stable/py/embeddings/simple_det.0.hash delete mode 100644 tests/cases/stable/py/embeddings/simple_det.0_0.hash delete mode 100644 tests/cases/stable/py/embeddings/simple_tokenizer.0.hash delete mode 100644 tests/cases/stable/py/embeddings/simple_tokenizer.0_0.hash delete mode 100644 tests/cases/stable/py/embeddings/vecdb.0.hash delete mode 100644 tests/cases/stable/py/events/post_event.0.hash delete mode 100644 tests/cases/stable/py/intercontract/call_view.0.hash delete mode 100644 tests/cases/stable/py/intercontract/call_view.0_0.hash delete mode 100644 tests/cases/stable/py/intercontract/call_view.0_0_0.hash delete mode 100644 tests/cases/stable/py/intercontract/call_view_iface.0.hash delete mode 100644 tests/cases/stable/py/intercontract/call_view_iface.0_0.hash delete mode 100644 tests/cases/stable/py/intercontract/call_view_iface.0_0_0.hash delete mode 100644 tests/cases/stable/py/intercontract/deploy.0.hash delete mode 100644 tests/cases/stable/py/intercontract/deploy_salt.0.hash delete mode 100644 tests/cases/stable/py/intercontract/eth_call_view.0.hash delete mode 100644 tests/cases/stable/py/intercontract/send_message.0.hash delete mode 100644 tests/cases/stable/py/intercontract/send_message_eth.0.hash delete mode 100644 tests/cases/stable/py/intercontract/send_message_on.0.hash delete mode 100644 tests/cases/stable/py/intercontract/send_message_on.0_0.hash delete mode 100644 tests/cases/stable/py/intercontract/send_message_on.0_0_0.hash delete mode 100644 tests/cases/stable/py/other/meth/method_init.0.hash delete mode 100644 tests/cases/stable/py/other/meth/method_init_wrong_name.0.hash delete mode 100644 tests/cases/stable/py/other/meth/method_public.0.hash delete mode 100644 tests/cases/stable/py/other/meth/method_public.0_0.hash delete mode 100644 tests/cases/stable/py/other/meth/method_retn.0.hash delete mode 100644 tests/cases/stable/py/other/meth/method_retn.0_0.hash delete mode 100644 tests/cases/stable/py/other/meth/method_retn_view.0.hash delete mode 100644 tests/cases/stable/py/other/meth/method_retn_view.0_0.hash delete mode 100644 tests/cases/stable/py/other/meth/method_rollback.0.hash delete mode 100644 tests/cases/stable/py/other/meth/method_rollback.0_0.hash delete mode 100644 tests/cases/stable/py/other/ret/returns.0.hash delete mode 100644 tests/cases/stable/py/other/ret/returns.0_0.hash delete mode 100644 tests/cases/stable/py/other/ret/returns.1.hash delete mode 100644 tests/cases/stable/py/other/ret/returns.1_0.hash delete mode 100644 tests/cases/stable/py/other/ret/returns.2.hash delete mode 100644 tests/cases/stable/py/other/ret/returns.2_0.hash delete mode 100644 tests/cases/stable/py/other/ret/returns.3.hash delete mode 100644 tests/cases/stable/py/other/ret/returns.3_0.hash delete mode 100644 tests/cases/stable/py/other/ret/returns.4.hash delete mode 100644 tests/cases/stable/py/other/ret/returns.4_0.hash delete mode 100644 tests/cases/stable/py/other/ret/returns.5.hash delete mode 100644 tests/cases/stable/py/other/ret/returns.5_0.hash delete mode 100644 tests/cases/stable/py/other/ret/returns.6.hash delete mode 100644 tests/cases/stable/py/other/ret/returns.6_0.hash delete mode 100644 tests/cases/stable/py/other/ret/returns.7.hash delete mode 100644 tests/cases/stable/py/other/ret/returns.7_0.hash delete mode 100644 tests/cases/stable/py/other/ret/returns.8.hash delete mode 100644 tests/cases/stable/py/other/ret/returns.8_0.hash delete mode 100644 tests/cases/stable/py/other/ret/returns.9.hash delete mode 100644 tests/cases/stable/py/other/ret/returns.9_0.hash delete mode 100644 tests/cases/stable/py/pitfalls/multi_contract.0.hash delete mode 100644 tests/cases/stable/py/pitfalls/pub_ctor.0.hash delete mode 100644 tests/cases/stable/py/pitfalls/store_proxy.0.hash delete mode 100644 tests/cases/stable/py/rollbacks/call_view.0.hash delete mode 100644 tests/cases/stable/py/rollbacks/call_view.0_0.hash delete mode 100644 tests/cases/stable/py/rollbacks/call_view.0_0_0.hash delete mode 100644 tests/cases/stable/py/rollbacks/calldata_rollback.0.hash delete mode 100644 tests/cases/stable/py/rollbacks/calldata_rollback.0_0.hash delete mode 100644 tests/cases/stable/py/rollbacks/calldata_rollback.0_0_0.hash delete mode 100644 tests/cases/stable/py/rollbacks/nondet.0.hash delete mode 100644 tests/cases/stable/py/rollbacks/simple.0.hash delete mode 100644 tests/cases/stable/py/sandbox/det/s/assign-json.0.hash delete mode 100644 tests/cases/stable/py/sandbox/det/s/assign-json.0_0.hash delete mode 100644 tests/cases/stable/py/sandbox/det/s/exit.0.hash delete mode 100644 tests/cases/stable/py/sandbox/det/s/exit.0_0.hash delete mode 100644 tests/cases/stable/py/sandbox/det/s/print.0.hash delete mode 100644 tests/cases/stable/py/sandbox/det/s/print.0_0.hash delete mode 100644 tests/cases/stable/py/sandbox/det/s/rollback.0.hash delete mode 100644 tests/cases/stable/py/sandbox/det/s/rollback.0_0.hash delete mode 100644 tests/cases/stable/py/sandbox/det/s/sandbox.0.hash delete mode 100644 tests/cases/stable/py/sandbox/det/s/sandbox.0_0.hash delete mode 100644 tests/cases/stable/py/sandbox/det/sandbox_write.0.hash delete mode 100644 tests/cases/stable/py/sandbox/non-det/s/assign-json.0.hash delete mode 100644 tests/cases/stable/py/sandbox/non-det/s/assign-json.0_0.hash delete mode 100644 tests/cases/stable/py/sandbox/non-det/s/exit.0.hash delete mode 100644 tests/cases/stable/py/sandbox/non-det/s/exit.0_0.hash delete mode 100644 tests/cases/stable/py/sandbox/non-det/s/print.0.hash delete mode 100644 tests/cases/stable/py/sandbox/non-det/s/print.0_0.hash delete mode 100644 tests/cases/stable/py/sandbox/non-det/s/rollback.0.hash delete mode 100644 tests/cases/stable/py/sandbox/non-det/s/rollback.0_0.hash delete mode 100644 tests/cases/stable/py/schemas/complex_types.0.hash delete mode 100644 tests/cases/stable/py/schemas/complex_types.0_0.hash delete mode 100644 tests/cases/stable/py/schemas/prim_types.0.hash delete mode 100644 tests/cases/stable/py/schemas/prim_types.0_0.hash delete mode 100644 tests/cases/stable/py/schemas/ret-float.0.hash delete mode 100644 tests/cases/stable/py/schemas/ret-float.0_0.hash delete mode 100644 tests/cases/stable/py/schemas/ret-tuple.0.hash delete mode 100644 tests/cases/stable/py/schemas/ret-tuple.0_0.hash delete mode 100644 tests/cases/stable/py/schemas/ret.0.hash delete mode 100644 tests/cases/stable/py/schemas/ret.0_0.hash delete mode 100644 tests/cases/stable/py/schemas/trivial.0.hash delete mode 100644 tests/cases/stable/py/schemas/trivial.0_0.hash delete mode 100644 tests/cases/stable/runners/dup-dependency.0.hash delete mode 100644 tests/cases/stable/runners/env-template.0.hash delete mode 100644 tests/cases/stable/runners/malformed_runner.0.hash delete mode 100644 tests/cases/stable/runners/no_runner.0.hash delete mode 100644 tests/cases/stable/runners/zip/no-zip.0.hash delete mode 100644 tests/cases/stable/self-run/datetime.0.hash delete mode 100644 tests/cases/stable/self-run/floats.0.hash delete mode 100644 tests/cases/stable/self-run/formats.0.hash delete mode 100644 tests/cases/stable/self-run/issue_163.0.hash delete mode 100644 tests/cases/stable/self-run/module/np.0.hash delete mode 100644 tests/cases/stable/self-run/module/pil.0.hash delete mode 100644 tests/cases/stable/self-run/re.0.hash delete mode 100644 tests/cases/stable/self-run/typing_is_ok.0.hash delete mode 100644 tests/cases/stable/storage/alloc_generic.0.hash delete mode 100644 tests/cases/stable/storage/alloc_generic_err.0.hash delete mode 100644 tests/cases/stable/storage/base.0.hash delete mode 100644 tests/cases/stable/storage/bootstrapper.0.hash delete mode 100644 tests/cases/stable/storage/bootstrapper.0_0.hash delete mode 100644 tests/cases/stable/storage/bootstrapper.0_0_0.hash delete mode 100644 tests/cases/stable/storage/bootstrapper.0_0_0_0.hash delete mode 100644 tests/cases/stable/storage/bootstrapper.0_0_0_0_0.hash delete mode 100644 tests/cases/stable/storage/bootstrapper.0_0_0_0_0_0.hash delete mode 100644 tests/cases/stable/storage/floats.0.hash delete mode 100644 tests/cases/stable/storage/gvm-89.0.hash delete mode 100644 tests/cases/stable/storage/gvm-89.0_0.hash delete mode 100644 tests/cases/stable/storage/locking/default-frozen.0.hash delete mode 100644 tests/cases/stable/storage/locking/default-frozen.0_0.hash delete mode 100644 tests/cases/stable/storage/locking/default-frozen.0_0_0.hash delete mode 100644 tests/cases/stable/storage/locking/modify_ctor.0.hash delete mode 100644 tests/cases/stable/storage/locking/modify_ctor.0_0.hash delete mode 100644 tests/cases/stable/storage/locking/modify_later.0.hash delete mode 100644 tests/cases/stable/storage/locking/modify_later.0_0.hash delete mode 100644 tests/cases/stable/storage/locking/modify_later.0_0_0.hash delete mode 100644 tests/cases/stable/storage/np.0.hash delete mode 100644 tests/cases/stable/storage/persists.0.hash delete mode 100644 tests/cases/stable/storage/persists.0_0.hash delete mode 100644 tests/cases/stable/storage/read_nondet.0.hash delete mode 100644 tests/cases/stable/storage/storage_tree_map.0.hash delete mode 100644 tests/cases/stable/storage/to_str.0.hash delete mode 100644 tests/cases/stable/storage/tree_map_nested.0.hash delete mode 100644 tests/cases/unstable/nondet/eq/ncomp/eq_prompt_non_comparative_validator.0.hash delete mode 100644 tests/cases/unstable/nondet/eq/ncomp/eq_prompt_non_comparative_validator_bad.0.hash delete mode 100644 tests/cases/unstable/nondet/validator/agree.0.hash delete mode 100644 tests/cases/unstable/nondet/validator/agree.0_0.hash delete mode 100644 tests/cases/unstable/nondet/validator/disagree.0.hash delete mode 100644 tests/cases/unstable/nondet/validator/disagree.0_0.hash delete mode 100644 tests/cases/unstable/nondet/web/get_webpage_html.0.hash delete mode 100644 tests/cases/unstable/nondet/web/get_webpage_screenshot.0.hash delete mode 100644 tests/cases/unstable/nondet/web/get_webpage_text.0.hash delete mode 100644 tests/cases/unstable/nondet/web/sandbox.0.hash diff --git a/executor/crates/common/src/bytes32.rs b/executor/crates/common/src/bytes32.rs index 964a5000d..41713e0a5 100644 --- a/executor/crates/common/src/bytes32.rs +++ b/executor/crates/common/src/bytes32.rs @@ -27,10 +27,47 @@ impl Bytes32Hash { genlayer_sdk::gvm32::encode(&self.0) } - /// Parses a hash from its GVM32 form. Returns `None` for an invalid encoding - /// or one that does not decode to exactly 32 bytes. - pub fn from_gvm32(s: &str) -> Option { - genlayer_sdk::gvm32::decode(s)?.try_into().ok().map(Self) + /// Parses a hash from its GVM32 form. + /// + /// Fails with [`FromGvm32Error::InvalidEncoding`] for a malformed encoding or + /// [`FromGvm32Error::WrongLength`] for one that does not decode to exactly 32 + /// bytes. + pub fn from_gvm32(s: &str) -> Result { + let bytes = genlayer_sdk::gvm32::decode(s).map_err(FromGvm32Error::InvalidEncoding)?; + let got = bytes.len(); + let bytes: [u8; 32] = bytes + .try_into() + .map_err(|_| FromGvm32Error::WrongLength { got })?; + Ok(Self(bytes)) + } +} + +/// Error returned by [`Bytes32Hash::from_gvm32`]. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum FromGvm32Error { + /// The string is not valid GVM32. + InvalidEncoding(genlayer_sdk::gvm32::DecodeError), + /// Decoded successfully, but not to exactly 32 bytes. + WrongLength { got: usize }, +} + +impl std::fmt::Display for FromGvm32Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + FromGvm32Error::InvalidEncoding(e) => write!(f, "invalid gvm32 encoding: {e}"), + FromGvm32Error::WrongLength { got } => { + write!(f, "expected 32 bytes, got {got}") + } + } + } +} + +impl std::error::Error for FromGvm32Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + FromGvm32Error::InvalidEncoding(e) => Some(e), + FromGvm32Error::WrongLength { .. } => None, + } } } diff --git a/executor/crates/common/tests/bytes32.rs b/executor/crates/common/tests/bytes32.rs index 8f0d090cf..22db664a2 100644 --- a/executor/crates/common/tests/bytes32.rs +++ b/executor/crates/common/tests/bytes32.rs @@ -1,3 +1,5 @@ +use genlayer_sdk::gvm32::DecodeError; +use genvm_common::bytes32::FromGvm32Error; use genvm_common::Bytes32Hash; #[test] @@ -7,13 +9,37 @@ fn gvm32_round_trip() { let s = h.to_gvm32(); assert_eq!(s.len(), 52); // ceil(256 / 5) - assert_eq!(Bytes32Hash::from_gvm32(&s), Some(h)); + assert_eq!(Bytes32Hash::from_gvm32(&s), Ok(h)); assert_eq!(h.to_string(), s); // Display == gvm32 assert_eq!(h.as_bytes(), &bytes); } #[test] fn from_gvm32_rejects_invalid() { - assert_eq!(Bytes32Hash::from_gvm32("abc"), None); // decodes to < 32 bytes - assert_eq!(Bytes32Hash::from_gvm32(""), None); // 0 bytes + // valid gvm32, but decodes to fewer than 32 bytes + assert_eq!( + Bytes32Hash::from_gvm32("00"), // decodes to 1 byte + Err(FromGvm32Error::WrongLength { got: 1 }) + ); + assert_eq!( + Bytes32Hash::from_gvm32(""), // decodes to 0 bytes + Err(FromGvm32Error::WrongLength { got: 0 }) + ); + // '!' is not in the alphabet + assert_eq!( + Bytes32Hash::from_gvm32("!"), + Err(FromGvm32Error::InvalidEncoding(DecodeError::InvalidChar( + '!' + ))) + ); + // valid alphabet, but non-zero trailing padding bits + assert_eq!( + Bytes32Hash::from_gvm32("abc"), + Err(FromGvm32Error::InvalidEncoding( + DecodeError::NonZeroPadding { + bits: 7, + value: 108 + } + )) + ); } diff --git a/executor/crates/sdk-rs/Cargo.lock b/executor/crates/sdk-rs/Cargo.lock index 4fac2d5cf..0fb63fa8d 100644 --- a/executor/crates/sdk-rs/Cargo.lock +++ b/executor/crates/sdk-rs/Cargo.lock @@ -246,6 +246,7 @@ dependencies = [ "num-bigint", "primitive-types", "serde", + "sha3", ] [[package]] diff --git a/executor/crates/sdk-rs/src/gvm32.rs b/executor/crates/sdk-rs/src/gvm32.rs index 2231d69e2..142db82c1 100644 --- a/executor/crates/sdk-rs/src/gvm32.rs +++ b/executor/crates/sdk-rs/src/gvm32.rs @@ -37,10 +37,38 @@ fn decode_char(c: u8) -> Option { ALPHABET.iter().position(|&b| b == c).map(|p| p as u8) } +/// Reason a [`decode`] call failed. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum DecodeError { + /// A character outside the Crockford Base32 alphabet (after the `i`/`l`/`o` + /// aliases and `-` handling). + InvalidChar(char), + /// The final group carried non-zero padding bits, so the input is not a + /// canonical encoding of any byte sequence. Carries the number of leftover + /// `bits` and their non-zero `value` to aid debugging. + NonZeroPadding { bits: u32, value: u32 }, +} + +impl core::fmt::Display for DecodeError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + DecodeError::InvalidChar(c) => write!(f, "invalid gvm32 character `{c}`"), + DecodeError::NonZeroPadding { bits, value } => write!( + f, + "non-zero gvm32 trailing padding: {bits} bit(s) = {value:#x}" + ), + } + } +} + +impl std::error::Error for DecodeError {} + /// Decodes a Crockford Base32 string. Case-insensitive; `i`/`l` are read as `1`, -/// `o` as `0` and `-` is ignored. Returns `None` on an invalid character or -/// non-zero trailing padding bits. -pub fn decode(s: &str) -> Option> { +/// `o` as `0` and `-` is ignored. +/// +/// Fails with [`DecodeError::InvalidChar`] on a character outside the alphabet +/// or [`DecodeError::NonZeroPadding`] on non-zero trailing padding bits. +pub fn decode(s: &str) -> Result, DecodeError> { let mut out = Vec::with_capacity(s.len() * 5 / 8); let mut value: u32 = 0; let mut bits: u32 = 0; @@ -48,7 +76,8 @@ pub fn decode(s: &str) -> Option> { if c == b'-' { continue; } - value = (value << 5) | decode_char(c)? as u32; + let digit = decode_char(c).ok_or(DecodeError::InvalidChar(c as char))?; + value = (value << 5) | digit as u32; bits += 5; if bits >= 8 { bits -= 8; @@ -57,7 +86,7 @@ pub fn decode(s: &str) -> Option> { } } if value != 0 { - return None; + return Err(DecodeError::NonZeroPadding { bits, value }); } - Some(out) + Ok(out) } diff --git a/executor/crates/sdk-rs/src/storage/array.rs b/executor/crates/sdk-rs/src/storage/array.rs index 19712ae76..f5896d88e 100644 --- a/executor/crates/sdk-rs/src/storage/array.rs +++ b/executor/crates/sdk-rs/src/storage/array.rs @@ -23,6 +23,10 @@ impl StorageArray { N } + pub const fn is_empty(&self) -> bool { + N == 0 + } + pub fn index(&self, idx: usize) -> T::Handle { assert!(idx < N, "index {idx} out of bounds for array of length {N}"); T::handle_at(self.slot, self.offset + idx as u32 * T::SIZE) diff --git a/executor/crates/sdk-rs/src/storage/mod.rs b/executor/crates/sdk-rs/src/storage/mod.rs index 33ebfaba9..e534b6e86 100644 --- a/executor/crates/sdk-rs/src/storage/mod.rs +++ b/executor/crates/sdk-rs/src/storage/mod.rs @@ -11,12 +11,16 @@ pub use self::tree_map::*; use crate::calldata::Address; +// Field order defines slot offsets; must match `root_offsets` in the public ABI +// and `Root` in runners/genlayer-py-std/.../storage/root.py: +// MAJOR=0, CONTRACT=1, CODE=2, LOCKED_SLOTS=3, UPGRADERS=4, CODE_SLOT=5. crate::record!(Root[T] { + major: u8, contract_instance: Indirection, code: Indirection>, locked_slots: Indirection>, upgraders: Indirection>, - major: u8, + code_slot: primitive_types::U256, }); impl Root { @@ -27,4 +31,19 @@ impl Root { pub fn get() -> Self { ::handle_at(Self::SLOT, 0) } + + /// Resolve the handle to the contract code. + /// + /// If `code_slot` is zero (the default), the code is read from the default + /// `code` indirection; otherwise it is read from the slot pointed to by + /// `code_slot` (see `chain:` runner ids). Mirrors `Root.get_resolved_code` + /// in the Python runner. + pub fn get_resolved_code(&self) -> StorageVLA { + let code_slot = self.code_slot().get(); + if code_slot.is_zero() { + self.code().get() + } else { + VLA::::handle_at(Slot(code_slot.to_little_endian()), 0) + } + } } diff --git a/executor/crates/sdk-rs/tests/gvm32.rs b/executor/crates/sdk-rs/tests/gvm32.rs index 52c877c6e..befd1d7fb 100644 --- a/executor/crates/sdk-rs/tests/gvm32.rs +++ b/executor/crates/sdk-rs/tests/gvm32.rs @@ -60,8 +60,12 @@ fn case_insensitive_and_aliases() { #[test] fn rejects_invalid() { + use gvm32::DecodeError; // `u` is not in the alphabet and is not an alias - assert_eq!(gvm32::decode("u"), None); + assert_eq!(gvm32::decode("u"), Err(DecodeError::InvalidChar('u'))); // non-zero trailing padding bits - assert_eq!(gvm32::decode("01"), None); + assert_eq!( + gvm32::decode("01"), + Err(DecodeError::NonZeroPadding { bits: 2, value: 1 }) + ); } diff --git a/executor/src/rt/errors.rs b/executor/src/rt/errors.rs index f3771741a..40194d6cd 100644 --- a/executor/src/rt/errors.rs +++ b/executor/src/rt/errors.rs @@ -11,14 +11,29 @@ impl std::error::Error for VMError {} impl std::fmt::Display for VMError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "VMError({})", self.0 .0) + if f.alternate() { + f.write_fmt(format_args!("VMError({},", self.0 .0))?; + if let Some(cause) = &self.1 { + f.write_fmt(format_args!("{})", cause))?; + } else { + f.write_str("None)")?; + return Ok(()); + }; + } else { + f.write_fmt(format_args!("VMError({})", self.0 .0))?; + } + + Ok(()) } } impl VMError { pub fn wrap>(message: abi::consts::VmError, cause: E) -> Self { match cause.into().downcast::() { - Err(cause) => Self(message, Some(cause)), + Err(cause) => { + log_debug!(vm_error = message.0, cause:ah = cause; "wrapping VMError"); + Self(message, Some(cause)) + } Ok(v) => v, } } diff --git a/executor/src/rt/mod.rs b/executor/src/rt/mod.rs index 641cf6220..f460c5116 100644 --- a/executor/src/rt/mod.rs +++ b/executor/src/rt/mod.rs @@ -77,6 +77,9 @@ pub async fn spawn_apply_run( ), SpawnErrorState::Unspawned(vm_data) => (Default::default(), vm_data), }; + + log_debug!(error:ah = error; "spawn_apply_run failed"); + match errors::unwrap_vm_errors_backtrace(errors::UnwrapDynError::from(error)) { Ok((run_ok, backtrace)) => Ok(vm::RunResult { run_ok, @@ -104,5 +107,6 @@ async fn spawn_apply_run_inner( } use anyhow::Context; +use genvm_common::log_debug; use crate::wasi; diff --git a/executor/src/rt/supervisor/actions.rs b/executor/src/rt/supervisor/actions.rs index f2d3fa6f7..36b107877 100644 --- a/executor/src/rt/supervisor/actions.rs +++ b/executor/src/rt/supervisor/actions.rs @@ -94,33 +94,31 @@ async fn resolve_runner( let resolved: runners::Id = match parsed.resolve(contract_address, state, code_slot) { runners::IdUnresolved::Contract => unreachable!("contract is resolved to chain"), runners::IdUnresolved::Builtin { name, hash } => { - let hash: Bytes32Hash = if hash == "test" { + let hash: Bytes32Hash = if hash == "test" || hash == "latest" { if !supervisor.shared_data.debug_mode.allows_latest_resolution() { - log_warn!(":test runner used in non-debug mode, this is not allowed"); - return Err(make_malformed_runner_error( - "runner id doesn't match expected format", - )); - } - runners::TEST_RUNNER_HASH - } else if hash == "latest" { - if !supervisor.shared_data.debug_mode.allows_latest_resolution() { - log_warn!(":latest runner used in non-debug mode, this is not allowed"); + log_warn!(":{hash} runner used in non-debug mode, this is not allowed"); return Err(make_malformed_runner_error( "runner id doesn't match expected format", )); } let new_latest = supervisor.runner_cache.get_latest(&name); - log_info!(runner_id = name.as_str(); "resolving :latest runner"); + log_info!(runner_id = name.as_str(), tag = hash.as_str(); "resolving :test/:latest runner"); let Some(new_latest) = new_latest else { return Err(make_malformed_runner_error( "runner id doesn't match expected format", )); }; - Bytes32Hash::from_gvm32(new_latest) - .ok_or_else(|| make_malformed_runner_error("runner hash is not valid gvm32"))? + Bytes32Hash::from_gvm32(new_latest).map_err(|e| { + make_malformed_runner_error(&format!( + "runner hash `{new_latest}` is not valid gvm32: {e}" + )) + })? } else { - Bytes32Hash::from_gvm32(&hash) - .ok_or_else(|| make_malformed_runner_error("runner hash is not valid gvm32"))? + Bytes32Hash::from_gvm32(&hash).map_err(|e| { + make_malformed_runner_error(&format!( + "runner hash `{hash}` is not valid gvm32: {e}" + )) + })? }; let hash_gvm32 = hash.to_gvm32(); @@ -160,8 +158,10 @@ async fn resolve_runner( runners::Id::Chain { address, on, slot } } runners::IdUnresolved::Custom { hash } => { - let hash = Bytes32Hash::from_gvm32(&hash).ok_or_else(|| { - make_malformed_runner_error("custom runner hash is not valid gvm32") + let hash = Bytes32Hash::from_gvm32(&hash).map_err(|e| { + make_malformed_runner_error(&format!( + "custom runner hash `{hash}` is not valid gvm32: {e}" + )) })?; runners::Id::Custom { hash } } @@ -330,7 +330,13 @@ pub(crate) fn map_archive_file( } if !name.starts_with(must_start_with) { - log_trace!(from = file, to = to, name = name; "aborting file mapping"); + log_trace!( + from = file, + to = to, + name = name, + must_start_with = must_start_with; + "aborting file mapping" + ); break; } @@ -645,9 +651,13 @@ impl Ctx<'_, '_> { return Ok(None); } - log_trace!(uid = resolved.id; "adding dependency"); + let uid = resolved.id.clone(); + log_trace!(uid = uid; "adding dependency"); - let (uid, new_arch) = self.get_arch(resolved).await?; + let (uid, new_arch) = self + .get_arch(resolved) + .await + .with_context(|| format!("getting archive for {uid}"))?; let new_action = new_arch .get_actions() @@ -656,7 +666,7 @@ impl Ctx<'_, '_> { Box::pin(self.apply(&new_action, uid, &new_arch)) .await - .with_context(|| format!("Depends {uid}")) + .with_context(|| format!("applying Depends {uid}")) } } } diff --git a/executor/src/rt/vm/storage.rs b/executor/src/rt/vm/storage.rs index 8c86b2b97..b96839cc2 100644 --- a/executor/src/rt/vm/storage.rs +++ b/executor/src/rt/vm/storage.rs @@ -165,6 +165,10 @@ impl Storage { } } +pub fn default_code_slot() -> SlotID { + SlotID::ZERO.indirection(root_offsets::CODE) +} + impl Storage { pub async fn read( &mut self, @@ -397,7 +401,7 @@ impl Storage { } pub async fn write_code(&mut self, code: &[u8]) -> anyhow::Result<()> { - let code_slot = SlotID::ZERO.indirection(root_offsets::CODE); + let code_slot = default_code_slot(); if code.len() > (u32::MAX - 4) as usize { return Err(rt::errors::VMError(abi::consts::VmError::oom().storage(), None).into()); @@ -436,7 +440,7 @@ impl Storage { self.read(SlotID::ZERO, root_offsets::CODE_SLOT, &mut raw) .await?; if raw == [0u8; 32] { - Ok(SlotID::ZERO.indirection(root_offsets::CODE)) + Ok(default_code_slot()) } else { Ok(SlotID::from_bytes(raw)) } diff --git a/executor/src/runners/mod.rs b/executor/src/runners/mod.rs index 96e34ea0f..4c05812d2 100644 --- a/executor/src/runners/mod.rs +++ b/executor/src/runners/mod.rs @@ -161,7 +161,7 @@ pub fn parse_runner_id(id: &str) -> Option { }; let slot = match slot_str { Some(s) => { - let bytes: [u8; 32] = genlayer_sdk::gvm32::decode(s)?.try_into().ok()?; + let bytes: [u8; 32] = genlayer_sdk::gvm32::decode(s).ok()?.try_into().ok()?; Some(crate::SlotID::from_bytes(bytes)) } None => None, diff --git a/modules/implementation/src/common/mod.rs b/modules/implementation/src/common/mod.rs index cb8439c4d..0f976f538 100644 --- a/modules/implementation/src/common/mod.rs +++ b/modules/implementation/src/common/mod.rs @@ -1,7 +1,7 @@ use base64::Engine; use genvm_common::*; use genvm_modules_interfaces::GenericValue; -use serde::{Deserialize, Serialize, Serializer}; +use serde::{Deserialize, Serialize}; use std::{collections::BTreeMap, sync::Arc}; use tokio::io::{AsyncReadExt, AsyncWriteExt}; diff --git a/modules/implementation/src/llm/merge.rs b/modules/implementation/src/llm/merge.rs index 0601641fb..56f9a7de5 100644 --- a/modules/implementation/src/llm/merge.rs +++ b/modules/implementation/src/llm/merge.rs @@ -156,175 +156,3 @@ pub fn merge_values( } } } - -#[cfg(test)] -mod tests { - use super::*; - use serde_json::json; - - #[test] - fn none_overwrites_scalars() { - let mut target = json!({"a": 1, "b": 2}); - merge_values(&mut target, json!({"a": 10, "c": 3}), MergeStrategy::None).unwrap(); - assert_eq!(target, json!({"a": 10, "b": 2, "c": 3})); - } - - #[test] - fn none_recurses_into_objects() { - let mut target = json!({"nested": {"a": 1, "b": 2}}); - merge_values( - &mut target, - json!({"nested": {"b": 20, "c": 3}}), - MergeStrategy::None, - ) - .unwrap(); - assert_eq!(target, json!({"nested": {"a": 1, "b": 20, "c": 3}})); - } - - #[test] - fn none_errors_on_arrays() { - let mut target = json!({"a": [1, 2]}); - let err = merge_values(&mut target, json!({"a": [3, 4]}), MergeStrategy::None); - assert!(err.is_err()); - } - - #[test] - fn replace_replaces_entirely() { - let mut target = json!({"a": 1, "b": 2}); - merge_values(&mut target, json!({"c": 3}), MergeStrategy::Replace).unwrap(); - assert_eq!(target, json!({"c": 3})); - } - - #[test] - fn merge_left_arrays() { - let mut target = json!([1, 2]); - merge_values(&mut target, json!([3, 4]), MergeStrategy::MergeLeft).unwrap(); - assert_eq!(target, json!([1, 2, 3, 4])); - } - - #[test] - fn merge_right_arrays() { - let mut target = json!([1, 2]); - merge_values(&mut target, json!([3, 4]), MergeStrategy::MergeRight).unwrap(); - assert_eq!(target, json!([3, 4, 1, 2])); - } - - #[test] - fn merge_left_strings() { - let mut target = json!("hello"); - merge_values(&mut target, json!(" world"), MergeStrategy::MergeLeft).unwrap(); - assert_eq!(target, json!("hello world")); - } - - #[test] - fn merge_right_strings() { - let mut target = json!("world"); - merge_values(&mut target, json!("hello "), MergeStrategy::MergeRight).unwrap(); - assert_eq!(target, json!("hello world")); - } - - #[test] - fn merge_left_errors_on_objects() { - let mut target = json!({"a": 1}); - let err = merge_values(&mut target, json!({"b": 2}), MergeStrategy::MergeLeft); - assert!(err.is_err()); - } - - #[test] - fn map_per_key_strategies() { - let mut target = json!({ - "items": [1, 2], - "name": "old", - "keep": "original" - }); - let strategy = MergeStrategy::Map(BTreeMap::from([ - ("items".into(), MergeStrategy::MergeLeft), - ("name".into(), MergeStrategy::Replace), - ])); - merge_values( - &mut target, - json!({"items": [3, 4], "name": "new", "extra": true}), - strategy, - ) - .unwrap(); - assert_eq!( - target, - json!({"items": [1, 2, 3, 4], "name": "new", "keep": "original", "extra": true}) - ); - } - - #[test] - fn map_default_errors_on_arrays() { - let mut target = json!({"a": [1]}); - let strategy = MergeStrategy::Map(BTreeMap::new()); - let err = merge_values(&mut target, json!({"a": [2]}), strategy); - assert!(err.is_err()); - } - - #[test] - fn map_inserts_missing_keys() { - let mut target = json!({"a": 1}); - let strategy = MergeStrategy::Map(BTreeMap::new()); - merge_values(&mut target, json!({"b": 2}), strategy).unwrap(); - assert_eq!(target, json!({"a": 1, "b": 2})); - } - - #[test] - fn merge_extra_applies_strategy() { - let mut request = json!({"model": "gpt-4", "temperature": 0.7}); - merge_extra( - &mut request, - json!({"temperature": 0.9, "top_p": 0.5}), - MergeStrategy::None, - ) - .unwrap(); - assert_eq!( - request, - json!({"model": "gpt-4", "temperature": 0.9, "top_p": 0.5}) - ); - } - - #[test] - fn deserialize_string_variants() { - assert!(matches!( - serde_json::from_value::(json!("none")).unwrap(), - MergeStrategy::None - )); - assert!(matches!( - serde_json::from_value::(json!("replace")).unwrap(), - MergeStrategy::Replace - )); - assert!(matches!( - serde_json::from_value::(json!("merge_left")).unwrap(), - MergeStrategy::MergeLeft - )); - assert!(matches!( - serde_json::from_value::(json!("merge_right")).unwrap(), - MergeStrategy::MergeRight - )); - } - - #[test] - fn deserialize_null_is_none() { - assert!(matches!( - serde_json::from_value::(json!(null)).unwrap(), - MergeStrategy::None - )); - } - - #[test] - fn deserialize_map() { - let strategy: MergeStrategy = - serde_json::from_value(json!({"items": "merge_left", "name": "replace"})).unwrap(); - let MergeStrategy::Map(map) = strategy else { - panic!("expected Map variant"); - }; - assert!(matches!(map.get("items"), Some(MergeStrategy::MergeLeft))); - assert!(matches!(map.get("name"), Some(MergeStrategy::Replace))); - } - - #[test] - fn deserialize_invalid_string_errors() { - assert!(serde_json::from_value::(json!("invalid")).is_err()); - } -} diff --git a/modules/implementation/src/manager/modules.rs b/modules/implementation/src/manager/modules.rs index c56083d38..3d7fdf0aa 100644 --- a/modules/implementation/src/manager/modules.rs +++ b/modules/implementation/src/manager/modules.rs @@ -92,6 +92,18 @@ pub struct StartRequest { pub user_error: bool, } +struct StartRealArgs +where + F: Fn() + Send + Sync + 'static, +{ + config: serde_json::Value, + allow_empty_backends: bool, + nested_cancel: Arc, + cancel_token: Arc, + canceller: F, + replace: bool, +} + /// Creates a stream handler that always responds with `Result::UserError` for every request. /// Maintains the wire protocol (reads hello, then loops reading messages and writing error responses). fn create_user_error_stream_handler() -> StreamHandler { @@ -223,12 +235,14 @@ impl Ctx { } else { self.start_real( req.module_type, - config, - req.allow_empty_backends, - nested_cancel, - module_cancel, - canceller, - replace, + StartRealArgs { + config, + allow_empty_backends: req.allow_empty_backends, + nested_cancel, + cancel_token: module_cancel, + canceller, + replace, + }, ) .await } @@ -299,16 +313,19 @@ impl Ctx { Ok(()) } - async fn start_real( - &self, - module_type: Type, - config: serde_json::Value, - allow_empty_backends: bool, - nested_cancel: Arc, - cancel_token: Arc, - canceller: impl Fn() + Send + Sync + 'static, - replace: bool, - ) -> anyhow::Result<()> { + async fn start_real(&self, module_type: Type, args: StartRealArgs) -> anyhow::Result<()> + where + F: Fn() + Send + Sync + 'static, + { + let StartRealArgs { + config, + allow_empty_backends, + nested_cancel, + cancel_token, + canceller, + replace, + } = args; + match module_type { Type::Llm => { let mut module_lock = self.llm_module.write().await; diff --git a/modules/implementation/src/scripting/ctx/req.rs b/modules/implementation/src/scripting/ctx/req.rs index bc5b2632a..f30f80f12 100644 --- a/modules/implementation/src/scripting/ctx/req.rs +++ b/modules/implementation/src/scripting/ctx/req.rs @@ -129,94 +129,3 @@ impl Request { }) } } - -#[cfg(test)] -mod tests { - use super::*; - use crate::common; - use genvm_common::*; - use genvm_modules_interfaces::web as web_iface; - - #[tokio::test] - async fn test_response_body_max_size_ok() { - common::tests::setup(); - - let client = common::tests::create_test_client(); - let metrics = sync::DArc::new(crate::scripting::ctx::Metrics::default()); - let url = "https://test-server.genlayer.com/body/echo"; - - // body within limit (500 bytes < 1024 limit) => success - let body = vec![b'a'; 500]; - let req = crate::scripting::ctx::req::Request { - url: url::Url::parse(url).unwrap(), - method: web_iface::RequestMethod::POST, - headers: BTreeMap::new(), - body: Some(body.clone()), - json: false, - error_on_status: false, - sign: false, - response_body_max_size: Some(1024), - timeout: None, - unfiltered: false, - headers_normalized: false, - }; - - let body_size_limit = req.response_body_max_size.unwrap_or(usize::MAX); - let reqwst = req.into_reqwest(&client).unwrap(); - - let res = crate::scripting::send_request_get_lua_compatible_response_bytes( - &metrics, - url, - reqwst, - false, - body_size_limit, - ) - .await - .unwrap(); - - assert_eq!(res.status, 200); - assert_eq!(res.body, body); - } - - #[tokio::test] - async fn test_response_body_max_size_exceeded() { - common::tests::setup(); - - let client = common::tests::create_test_client(); - let metrics = sync::DArc::new(crate::scripting::ctx::Metrics::default()); - let url = "https://test-server.genlayer.com/body/echo"; - - let body = vec![b'b'; 2000]; - let req = crate::scripting::ctx::req::Request { - url: url::Url::parse(url).unwrap(), - method: web_iface::RequestMethod::POST, - headers: BTreeMap::new(), - body: Some(body), - json: false, - error_on_status: false, - sign: false, - response_body_max_size: Some(1024), - timeout: None, - unfiltered: false, - headers_normalized: false, - }; - - let body_size_limit = 1024; - let reqwst = req.into_reqwest(&client).unwrap(); - - let err = crate::scripting::send_request_get_lua_compatible_response_bytes( - &metrics, - url, - reqwst, - false, - body_size_limit, - ) - .await - .unwrap_err(); - - log_info!(error:ah = &err; "Received expected error for exceeding body size limit"); - - let module_err = err.downcast::().unwrap(); - assert!(module_err.causes.contains(&"READING_BODY".to_owned())); - } -} diff --git a/modules/implementation/src/scripting/ctx/signing.rs b/modules/implementation/src/scripting/ctx/signing.rs index 2cf6f6a69..2922ad59d 100644 --- a/modules/implementation/src/scripting/ctx/signing.rs +++ b/modules/implementation/src/scripting/ctx/signing.rs @@ -295,9 +295,7 @@ mod tests { use std::collections::BTreeMap; use crate::common; - use genvm_common::*; use genvm_modules_interfaces::web as web_iface; - use std::sync::Arc; #[tokio::test] async fn test_signing_get() { @@ -420,62 +418,4 @@ mod tests { let base = base.trim(); assert_eq!(signature_base.trim(), base); } - - #[tokio::test] - async fn test_signing_post_with_server() { - use crate::scripting::ctx::CtxPart; - - common::tests::setup(); - - let mut req = crate::scripting::ctx::req::Request { - url: url::Url::parse("https://test-server.genlayer.com/body/echo-signed").unwrap(), - method: web_iface::RequestMethod::POST, - headers: BTreeMap::new(), - body: Some(b"test body".to_vec()), - json: false, - error_on_status: true, - sign: true, - response_body_max_size: None, - timeout: None, - unfiltered: false, - headers_normalized: false, - }; - - let part = CtxPart { - hello: Arc::new(genvm_modules_interfaces::GenVMHello { - genvm_id: genvm_modules_interfaces::GenVMId(999), - role: genvm_modules_interfaces::Role::Leader, - host_data: genvm_modules_interfaces::HostData { - node_address: "test_address".to_string(), - tx_id: "test_tx_id".to_string(), - rest: serde_json::Map::new(), - }, - gas_data: std::collections::BTreeMap::new(), - initial_time_units_allocation: 0, - }), - client: common::tests::create_test_client(), - client_unfiltered: common::tests::create_test_client(), - sign_url: Arc::from("https://test-server.genlayer.com/genvm/sign"), - sign_headers: Arc::new(BTreeMap::new()), - sign_vars: BTreeMap::new(), - node_address: "node_address".to_string(), - metrics: sync::DArc::new(crate::scripting::ctx::Metrics::default()), - }; - - req.add_rfc9421_sign_headers(&part).await.unwrap(); - - eprintln!("req: {req:?}"); - - let reqwst = req.into_reqwest(&part.client).unwrap(); - - let res = reqwst.send().await.unwrap(); - let status = res.status(); - let body = res.bytes().await; - eprintln!("Response status: {status:?}, body: {body:?}"); - assert_eq!(status, 200); - - let body = body.unwrap(); - - assert_eq!(body.as_ref(), b"test body"); - } } diff --git a/modules/implementation/src/scripting/mod.rs b/modules/implementation/src/scripting/mod.rs index 4bbaabb00..b08470024 100644 --- a/modules/implementation/src/scripting/mod.rs +++ b/modules/implementation/src/scripting/mod.rs @@ -13,6 +13,7 @@ use std::{collections::BTreeMap, future::Future, sync::Arc}; use crate::common::{self, ModuleError}; pub use ctx::filters; +pub use ctx::req::Request; pub use ctx::CtxPart; pub use ctx::Metrics; diff --git a/modules/implementation/tests/merge.rs b/modules/implementation/tests/merge.rs new file mode 100644 index 000000000..6aa9cec30 --- /dev/null +++ b/modules/implementation/tests/merge.rs @@ -0,0 +1,169 @@ +use genvm_modules::llm::merge::{merge_extra, merge_values, MergeStrategy}; +use serde_json::json; +use std::collections::BTreeMap; + +#[test] +fn none_overwrites_scalars() { + let mut target = json!({"a": 1, "b": 2}); + merge_values(&mut target, json!({"a": 10, "c": 3}), MergeStrategy::None).unwrap(); + assert_eq!(target, json!({"a": 10, "b": 2, "c": 3})); +} + +#[test] +fn none_recurses_into_objects() { + let mut target = json!({"nested": {"a": 1, "b": 2}}); + merge_values( + &mut target, + json!({"nested": {"b": 20, "c": 3}}), + MergeStrategy::None, + ) + .unwrap(); + assert_eq!(target, json!({"nested": {"a": 1, "b": 20, "c": 3}})); +} + +#[test] +fn none_errors_on_arrays() { + let mut target = json!({"a": [1, 2]}); + let err = merge_values(&mut target, json!({"a": [3, 4]}), MergeStrategy::None); + assert!(err.is_err()); +} + +#[test] +fn replace_replaces_entirely() { + let mut target = json!({"a": 1, "b": 2}); + merge_values(&mut target, json!({"c": 3}), MergeStrategy::Replace).unwrap(); + assert_eq!(target, json!({"c": 3})); +} + +#[test] +fn merge_left_arrays() { + let mut target = json!([1, 2]); + merge_values(&mut target, json!([3, 4]), MergeStrategy::MergeLeft).unwrap(); + assert_eq!(target, json!([1, 2, 3, 4])); +} + +#[test] +fn merge_right_arrays() { + let mut target = json!([1, 2]); + merge_values(&mut target, json!([3, 4]), MergeStrategy::MergeRight).unwrap(); + assert_eq!(target, json!([3, 4, 1, 2])); +} + +#[test] +fn merge_left_strings() { + let mut target = json!("hello"); + merge_values(&mut target, json!(" world"), MergeStrategy::MergeLeft).unwrap(); + assert_eq!(target, json!("hello world")); +} + +#[test] +fn merge_right_strings() { + let mut target = json!("world"); + merge_values(&mut target, json!("hello "), MergeStrategy::MergeRight).unwrap(); + assert_eq!(target, json!("hello world")); +} + +#[test] +fn merge_left_errors_on_objects() { + let mut target = json!({"a": 1}); + let err = merge_values(&mut target, json!({"b": 2}), MergeStrategy::MergeLeft); + assert!(err.is_err()); +} + +#[test] +fn map_per_key_strategies() { + let mut target = json!({ + "items": [1, 2], + "name": "old", + "keep": "original" + }); + let strategy = MergeStrategy::Map(BTreeMap::from([ + ("items".into(), MergeStrategy::MergeLeft), + ("name".into(), MergeStrategy::Replace), + ])); + merge_values( + &mut target, + json!({"items": [3, 4], "name": "new", "extra": true}), + strategy, + ) + .unwrap(); + assert_eq!( + target, + json!({"items": [1, 2, 3, 4], "name": "new", "keep": "original", "extra": true}) + ); +} + +#[test] +fn map_default_errors_on_arrays() { + let mut target = json!({"a": [1]}); + let strategy = MergeStrategy::Map(BTreeMap::new()); + let err = merge_values(&mut target, json!({"a": [2]}), strategy); + assert!(err.is_err()); +} + +#[test] +fn map_inserts_missing_keys() { + let mut target = json!({"a": 1}); + let strategy = MergeStrategy::Map(BTreeMap::new()); + merge_values(&mut target, json!({"b": 2}), strategy).unwrap(); + assert_eq!(target, json!({"a": 1, "b": 2})); +} + +#[test] +fn merge_extra_applies_strategy() { + let mut request = json!({"model": "gpt-4", "temperature": 0.7}); + merge_extra( + &mut request, + json!({"temperature": 0.9, "top_p": 0.5}), + MergeStrategy::None, + ) + .unwrap(); + assert_eq!( + request, + json!({"model": "gpt-4", "temperature": 0.9, "top_p": 0.5}) + ); +} + +#[test] +fn deserialize_string_variants() { + assert!(matches!( + serde_json::from_value::(json!("none")).unwrap(), + MergeStrategy::None + )); + assert!(matches!( + serde_json::from_value::(json!("replace")).unwrap(), + MergeStrategy::Replace + )); + assert!(matches!( + serde_json::from_value::(json!("merge_left")).unwrap(), + MergeStrategy::MergeLeft + )); + assert!(matches!( + serde_json::from_value::(json!("merge_right")).unwrap(), + MergeStrategy::MergeRight + )); +} + +#[test] +fn deserialize_null_is_none() { + assert!(matches!( + serde_json::from_value::(json!(null)).unwrap(), + MergeStrategy::None + )); +} + +#[test] +fn deserialize_map() { + let strategy: MergeStrategy = + serde_json::from_value(json!({"items": "merge_left", "name": "replace"})).unwrap(); + let MergeStrategy::Map(map) = strategy else { + panic!("expected Map variant"); + }; + assert!(matches!(map.get("items"), Some(MergeStrategy::MergeLeft))); + assert!(matches!(map.get("name"), Some(MergeStrategy::Replace))); +} + +#[test] +fn deserialize_invalid_string_errors() { + assert!(serde_json::from_value::(json!("invalid")).is_err()); +} diff --git a/modules/implementation/tests/request_body_limit.rs b/modules/implementation/tests/request_body_limit.rs new file mode 100644 index 000000000..6cfa568f2 --- /dev/null +++ b/modules/implementation/tests/request_body_limit.rs @@ -0,0 +1,88 @@ +use std::collections::BTreeMap; + +use genvm_common::*; +use genvm_modules_interfaces::web as web_iface; + +use genvm_modules::common; + +#[tokio::test] +async fn response_body_max_size_ok() { + common::tests::setup(); + + let client = common::tests::create_test_client(); + let metrics = sync::DArc::new(genvm_modules::scripting::Metrics::default()); + let url = "https://test-server.genlayer.com/body/echo"; + + let body = vec![b'a'; 500]; + let req = genvm_modules::scripting::Request { + url: url::Url::parse(url).unwrap(), + method: web_iface::RequestMethod::POST, + headers: BTreeMap::new(), + body: Some(body.clone()), + json: false, + error_on_status: false, + sign: false, + response_body_max_size: Some(1024), + timeout: None, + unfiltered: false, + headers_normalized: false, + }; + + let body_size_limit = req.response_body_max_size.unwrap_or(usize::MAX); + let reqwst = req.into_reqwest(&client).unwrap(); + + let res = genvm_modules::scripting::send_request_get_lua_compatible_response_bytes( + &metrics, + url, + reqwst, + false, + body_size_limit, + ) + .await + .unwrap(); + + assert_eq!(res.status, 200); + assert_eq!(res.body, body); +} + +#[tokio::test] +async fn response_body_max_size_exceeded() { + common::tests::setup(); + + let client = common::tests::create_test_client(); + let metrics = sync::DArc::new(genvm_modules::scripting::Metrics::default()); + let url = "https://test-server.genlayer.com/body/echo"; + + let body = vec![b'b'; 2000]; + let req = genvm_modules::scripting::Request { + url: url::Url::parse(url).unwrap(), + method: web_iface::RequestMethod::POST, + headers: BTreeMap::new(), + body: Some(body), + json: false, + error_on_status: false, + sign: false, + response_body_max_size: Some(1024), + timeout: None, + unfiltered: false, + headers_normalized: false, + }; + + let body_size_limit = 1024; + let reqwst = req.into_reqwest(&client).unwrap(); + + let err = genvm_modules::scripting::send_request_get_lua_compatible_response_bytes( + &metrics, + url, + reqwst, + false, + body_size_limit, + ) + .await + .unwrap_err(); + + let module_err = err + .downcast::() + .unwrap(); + assert!(module_err.causes.contains(&"READING_BODY".to_owned())); +} diff --git a/modules/implementation/tests/signing_server.rs b/modules/implementation/tests/signing_server.rs new file mode 100644 index 000000000..bbe57d7da --- /dev/null +++ b/modules/implementation/tests/signing_server.rs @@ -0,0 +1,60 @@ +use std::collections::BTreeMap; +use std::sync::Arc; + +use genvm_common::*; +use genvm_modules_interfaces::web as web_iface; + +use genvm_modules::common; +use genvm_modules::scripting::CtxPart; + +#[tokio::test] +async fn signing_post_with_server() { + common::tests::setup(); + + let mut req = genvm_modules::scripting::Request { + url: url::Url::parse("https://test-server.genlayer.com/body/echo-signed").unwrap(), + method: web_iface::RequestMethod::POST, + headers: BTreeMap::new(), + body: Some(b"test body".to_vec()), + json: false, + error_on_status: true, + sign: true, + response_body_max_size: None, + timeout: None, + unfiltered: false, + headers_normalized: false, + }; + + let part = CtxPart { + hello: Arc::new(genvm_modules_interfaces::GenVMHello { + genvm_id: genvm_modules_interfaces::GenVMId(999), + role: genvm_modules_interfaces::Role::Leader, + host_data: genvm_modules_interfaces::HostData { + node_address: "test_address".to_string(), + tx_id: "test_tx_id".to_string(), + rest: serde_json::Map::new(), + }, + gas_data: std::collections::BTreeMap::new(), + initial_time_units_allocation: 0, + }), + client: common::tests::create_test_client(), + client_unfiltered: common::tests::create_test_client(), + sign_url: Arc::from("https://test-server.genlayer.com/genvm/sign"), + sign_headers: Arc::new(BTreeMap::new()), + sign_vars: BTreeMap::new(), + node_address: "node_address".to_string(), + metrics: sync::DArc::new(genvm_modules::scripting::Metrics::default()), + }; + + req.add_rfc9421_sign_headers(&part).await.unwrap(); + + let reqwst = req.into_reqwest(&part.client).unwrap(); + + let res = reqwst.send().await.unwrap(); + let status = res.status(); + let body = res.bytes().await; + assert_eq!(status, 200); + + let body = body.unwrap(); + assert_eq!(body.as_ref(), b"test body"); +} diff --git a/modules/interfaces/Cargo.lock b/modules/interfaces/Cargo.lock index 15f66bfc7..02f679560 100644 --- a/modules/interfaces/Cargo.lock +++ b/modules/interfaces/Cargo.lock @@ -258,6 +258,7 @@ dependencies = [ "num-bigint", "primitive-types", "serde", + "sha3", ] [[package]] diff --git a/runners/genlayer-py-std/src/genlayer/_internal/on_chain/storage.py b/runners/genlayer-py-std/src/genlayer/_internal/on_chain/storage.py index deec49173..3797cc6a7 100644 --- a/runners/genlayer-py-std/src/genlayer/_internal/on_chain/storage.py +++ b/runners/genlayer-py-std/src/genlayer/_internal/on_chain/storage.py @@ -1,6 +1,6 @@ __all__ = ('STORAGE_MAN', 'ROOT_SLOT_ID') -from genlayer.storage.core import Manager, Slot, ROOT_SLOT_ID +from genlayer.storage.core import Manager, Slot, ROOT_SLOT_ID, slot_id_to_bytes from genlayer.types import u256 import _genlayer_wasi as wasi @@ -15,7 +15,8 @@ class _ActualStorageMan(Manager): def __init__(self): self._slots = {} - def get_store_slot(self, addr: bytes) -> Slot: + def get_store_slot(self, addr: bytes | u256) -> Slot: + addr = slot_id_to_bytes(addr) ret = self._slots.get(addr, None) if ret is None: ret = Slot(addr, self) diff --git a/runners/genlayer-py-std/src/genlayer/storage/core.py b/runners/genlayer-py-std/src/genlayer/storage/core.py index 53c88d5f4..fc9a10399 100644 --- a/runners/genlayer-py-std/src/genlayer/storage/core.py +++ b/runners/genlayer-py-std/src/genlayer/storage/core.py @@ -7,20 +7,33 @@ from genlayer.types import u256 +def slot_id_to_bytes(slot_id: u256 | bytes) -> bytes: + if isinstance(slot_id, int): + return slot_id.to_bytes(32, 'little', signed=False) + elif isinstance(slot_id, bytes): + if len(slot_id) != 32: + raise ValueError(f'slot_id must be 32 bytes, got {len(slot_id)}') + return slot_id + else: + raise TypeError(f'slot_id must be u256 or bytes, got {type(slot_id)}') + + class Manager(metaclass=abc.ABCMeta): """ Abstract interface for storage backends. """ - def get_store_slot(self, slot_id: bytes, /) -> 'Slot': + @abc.abstractmethod + def get_store_slot(self, slot_id: bytes | u256, /) -> 'Slot': """ Return a slot for the given address, creating one if necessary. - :param slot_id: 32-byte slot address + :param slot_id: 32-byte slot address or 256-bit slot address :returns: storage slot """ ... + @abc.abstractmethod def do_read(self, slot_id: bytes, off: int, len: int, /) -> bytes: """ Read raw bytes from storage. @@ -32,6 +45,7 @@ def do_read(self, slot_id: bytes, off: int, len: int, /) -> bytes: """ ... + @abc.abstractmethod def do_write(self, slot_id: bytes, off: int, what: collections.abc.Buffer, /): """ Write raw bytes to storage. @@ -496,7 +510,8 @@ class InmemManager(Manager): def __init__(self): self._parts = {} - def get_store_slot(self, id: bytes) -> Slot: + def get_store_slot(self, id: bytes | u256) -> Slot: + id = slot_id_to_bytes(id) res = self._parts.get(id, None) if res is None: slt = Slot(id, self) diff --git a/runners/genlayer-py-std/src/genlayer/storage/root.py b/runners/genlayer-py-std/src/genlayer/storage/root.py index 63fa0dd2f..51ea48993 100644 --- a/runners/genlayer-py-std/src/genlayer/storage/root.py +++ b/runners/genlayer-py-std/src/genlayer/storage/root.py @@ -69,6 +69,17 @@ def slot(self) -> Slot: """ return self._storage_slot # type: ignore + def get_resolved_code(self) -> VLA[u8]: + """ + Return the storage slot where the contract code is stored. + + :returns: code storage slot + """ + if self.code_slot == 0: + return self.code.get() + else: + return Root.MANAGER.get_store_slot(self.code_slot).cast(VLA[u8], 0) + def get_vacant_slot(self) -> Slot: """ This slot can be used to store data without worrying about overwriting contract data. diff --git a/runners/genlayer-py-std/src/genlayer/vm/__init__.py b/runners/genlayer-py-std/src/genlayer/vm/__init__.py index f46513bfd..151865933 100644 --- a/runners/genlayer-py-std/src/genlayer/vm/__init__.py +++ b/runners/genlayer-py-std/src/genlayer/vm/__init__.py @@ -119,11 +119,7 @@ def _decode_sub_vm_result_retn( ) -> Result: mem = memoryview(data) if mem[0] == ResultCode.USER_ERROR: - payload = mem[1:] - if len(payload) >= 4 and bytes(payload[:4]) == b'\x00\x00\x00\x00': - return UserError(calldata.decode(payload[4:])) - else: - return UserError(str(payload, encoding='utf8')) + return UserError(calldata.decode(mem[1:])) if mem[0] == ResultCode.RETURN: return Return(calldata.decode(mem[1:])) if mem[0] == ResultCode.VM_ERROR: diff --git a/runners/support/default.nix b/runners/support/default.nix index 05b26b380..730e4ac0a 100644 --- a/runners/support/default.nix +++ b/runners/support/default.nix @@ -15,7 +15,7 @@ in rec { add-mod-name = import ./tools/genvm-wasm-add-mod-name args; }; - gvm32 = import ./gvm32.nix { lib = pkgs.lib; }; + gvm32 = import ./gvm32.nix; # dev-mode magic hash: the literal gvm32 string "test" padded with "0"s to 52 chars testRunnerHash = "test" + (builtins.concatStringsSep "" (builtins.genList (_: "0") 48)); hashToIDHash = hash: if hash == "test" then testRunnerHash else gvm32.encodeHex (builtins.convertHash { inherit hash; toHashFormat = "base16"; }); diff --git a/runners/support/gvm32.nix b/runners/support/gvm32.nix index 21e34eff4..6214e56a6 100644 --- a/runners/support/gvm32.nix +++ b/runners/support/gvm32.nix @@ -4,13 +4,20 @@ # runners/genlayer-py-std/src/genlayer/gvm32.py. Used to derive runner content # hash ids. Implemented per output symbol (not by accumulating the whole value) # so it never overflows Nix's 64-bit integers, even for long hashes. -{ lib }: +# +# Pure: depends only on `builtins`, so it can be imported from contexts that do +# not have nixpkgs `lib` (e.g. versions/current.nix). let - alphabet = lib.stringToCharacters "0123456789abcdefghjkmnpqrstvwxyz"; + # string -> list of single-character strings (like lib.stringToCharacters) + stringToChars = s: + builtins.genList (i: builtins.substring i 1 s) (builtins.stringLength s); + + alphabet = stringToChars "0123456789abcdefghjkmnpqrstvwxyz"; # Nix `/` is integer division for ints; there is no `%` operator. mod = a: b: a - b * (a / b); - pow2 = n: builtins.foldl' (acc: _: acc * 2) 1 (lib.range 1 n); + # 2^n; the generated list's elements are irrelevant, only its length matters. + pow2 = n: builtins.foldl' (acc: _: acc * 2) 1 (builtins.genList (x: x) n); hexValues = { "0" = 0; "1" = 1; "2" = 2; "3" = 3; "4" = 4; "5" = 5; "6" = 6; "7" = 7; @@ -21,7 +28,7 @@ let # hex string -> list of byte integers hexToBytes = hex: let - chars = lib.stringToCharacters hex; + chars = stringToChars hex; charsLen = builtins.length chars; # integer division truncates, so reject odd lengths instead of # silently dropping the final nibble (which would corrupt the hash). @@ -52,7 +59,7 @@ let in builtins.elemAt alphabet v; in - lib.concatStrings (builtins.genList symAt nsym); + builtins.concatStringsSep "" (builtins.genList symAt nsym); encodeHex = hex: encode (hexToBytes hex); in diff --git a/runners/support/versions/current.nix b/runners/support/versions/current.nix index c2f5742ca..6f2fa9b77 100644 --- a/runners/support/versions/current.nix +++ b/runners/support/versions/current.nix @@ -1,6 +1,11 @@ let dev-mode = import ./dev-mode.nix; + # gvm32 (Crockford Base32) — the encoding the executor uses for runner hash + # ids. The embedded `uid` (consumed by `Depends`) MUST use this, matching the + # on-disk runner paths and `hashToIDHash` in ../default.nix. + gvm32 = import ../gvm32.nix; + src = rec { __prefix = ""; @@ -8,7 +13,7 @@ let __prefix = "models-"; all-MiniLM-L6-v2 = { - hash = "test"; + hash = "sha256-OlZQmCyKA+ct9hV4G12vSRUYUYB2S1CdDjIG2ueaOjQ="; }; }; @@ -16,22 +21,22 @@ let __prefix = "py-lib-"; cloudpickle = { - hash = "test"; + hash = "sha256-X/SQxZDU/Ep9D5ptzccqMiewgUh6mtt3vMyA+ZnqrHA="; }; protobuf = { - hash = "test"; + hash = "sha256-i0mGEqZ5XvoYCK5EZLZe48BltX8UYDxsiBQ8wJDratE="; }; word_piece_tokenizer = { - hash = "test"; + hash = "sha256-3T57N4bs1eSBaudAg0Dwi87d7kbu+anEYlGFH4Q3ujA="; }; genlayer-std = { - hash = "test"; + hash = "sha256-S4iSRVAS2wiavW9WmBriJ+svcJi6V67ybR/uSmYK+a0="; }; genlayer-embeddings = { - hash = "test"; + hash = "sha256-Lw2tC5IdLPhw4M+Zfp2igB9NUI9m3PgNyUmb9GMSQWQ="; depends = [ models.all-MiniLM-L6-v2 @@ -42,20 +47,20 @@ let }; cpython = { - hash = "test"; + hash = "sha256-LqsYHYqiAYnwDoXMpHOQHqvQCa+Dh9562J5ClfEggxI="; depends = [ softfloat ]; }; softfloat = { - hash = "test"; + hash = "sha256-aR7i/mGXm+x7ofoL7iJ1zUHsVyqkAsZG0mQ/Lj1+l4c="; }; wrappers = { __prefix = ""; py-genlayer = { - hash = "test"; + hash = "sha256-8Z0LeUX7ApxuBoi+Q/esPRLFO9i7ozaC2iEUb0idy8k="; depends = [ cpython pyLibs.cloudpickle @@ -63,7 +68,7 @@ let ]; }; py-genlayer-multi = { - hash = "test"; + hash = "sha256-Vhwo4+ksqqRSp9BGDcHz461UiDXfb3g8rdLrqIAkLB0="; depends = [ cpython pyLibs.cloudpickle @@ -132,7 +137,7 @@ let if deducedHash == null then fakeHash else deducedHash; - hash32 = if deducedHash == "test" then "test" else builtins.convertHash { hash = hashSRI; toHashFormat = "nix32"; }; + hash32 = if deducedHash == "test" then "test" else gvm32.encodeHex (builtins.convertHash { hash = hashSRI; toHashFormat = "base16"; }); in rec { id = pref + name; diff --git a/runners/support/versions/dev-mode.nix b/runners/support/versions/dev-mode.nix index 27ba77dda..c508d5366 100644 --- a/runners/support/versions/dev-mode.nix +++ b/runners/support/versions/dev-mode.nix @@ -1 +1 @@ -true +false diff --git a/runners/support/versions/generation-00.nix b/runners/support/versions/generation-00.nix index c16579660..33cd33a39 100644 --- a/runners/support/versions/generation-00.nix +++ b/runners/support/versions/generation-00.nix @@ -4,53 +4,8 @@ }: let revs = [ - "86b7cce46d9dee4ed1fb76e8107e60617b7622db" # v0.2.0 - "de381dbc862575b2a4f3d43a1b96ec14814af9fd" # v0.2.3 - "fed444c0d9537f41a6ccafeac7c7507a2cd8f69e" # v0.2.4 ]; - # These frozen v0.2.x runner trees hardcode the upstream zlib tarball URL in - # runners/cpython/deps/zlib.nix with NO mirror. The current ("head") recipe - # fetches the SAME genvm-zlib-src output (identical name + sha256, via - # dependency-urls.json) but with a mirror list — so both produce the same - # /nix/store output path through two different .drvs. nix realizes only one of - # them, non-deterministically: pick the head .drv and the dead zlib.net URL - # falls back to the GCS mirror and builds; pick this frozen .drv and there is - # no mirror, so it 404s and the whole runners-all build fails (~50% of - # from-source CI builds). zlib.net moved 1.3.1 under /fossils/, hence the 404. - # We rewrite the dead URL to the genvm-artifacts GCS mirror — the same artifact - # the head recipe already falls back to, which we control — in a copy of the - # fetched tree before importing it, so BOTH .drvs are resilient regardless of - # which one nix schedules. fetchzip is content-addressed by its sha256, so the - # genvm-zlib-src output path (and every downstream runner output hash) is - # unchanged; only the source URL changes. The grep guard fails loudly if a rev - # no longer carries the expected dead URL, so this never silently no-ops. - # - # IMPORTANT: --preserve=mode + a content-only rewrite of zlib.nix. The frozen - # trees ship executable build scripts (e.g. numpy's deps/stub-clang.py, 0755); - # a blanket `cp --no-preserve=mode` strips those bits and the numpy configure - # phase dies with exit 126 (Permission denied). So we keep every file's mode - # and touch ONLY zlib.nix's contents — the rest of the tree stays byte- and - # mode-identical, so downstream runner FOD outputs match their pinned hashes. - patchOldSrc = rev: src: - pkgs.runCommandLocal - "genvm-runners-src-${builtins.substring 0 12 rev}-zlib-mirror" - { } - '' - cp -r --preserve=mode ${src} "$out" - zlibNix="$out/runners/cpython/deps/zlib.nix" - if ! grep -q 'https://www.zlib.net/zlib-1.3.1.tar.gz' "$zlibNix"; then - echo "generation-00 zlib patch: expected dead URL not found in $zlibNix (rev ${rev}); patch is stale" >&2 - exit 1 - fi - chmod u+w "$zlibNix" - tmp="$(mktemp)" - sed 's|https://www.zlib.net/zlib-1.3.1.tar.gz|https://storage.googleapis.com/genvm-artifacts/zlib-1.3.1.tar.gz|g' \ - "$zlibNix" > "$tmp" - cat "$tmp" > "$zlibNix" - rm -f "$tmp" - ''; - mapRev = rev: let src = builtins.fetchGit { @@ -60,9 +15,8 @@ let shallow = true; submodules = true; }; - patchedSrc = patchOldSrc rev src; in - builtins.map (x: x // { inherit rev; }) (import "${patchedSrc}/runners") + builtins.map (x: x // { inherit rev; }) (import "${src}/runners") ; in # list[{id, hash, rev, derivation}] diff --git a/runners/support/versions/hash-updater.py b/runners/support/versions/hash-updater.py new file mode 100755 index 000000000..edcdf58ec --- /dev/null +++ b/runners/support/versions/hash-updater.py @@ -0,0 +1,212 @@ +#!/usr/bin/env python3 +"""Automatically fill in runner hashes in ``current.nix``. + +Runner archives are content-addressed. A runner's hash also depends on the +*resolved uids* of its dependencies, so the hashes must be discovered in +dependency order: a composite runner (e.g. ``cpython`` -> ``softfloat``, or the +``py-genlayer`` wrappers -> ``cpython``) only hashes correctly once every +dependency already carries its real hash. + +This script drives that to a fixed point: it builds ``#debug-runners`` with +``--keep-going``, scrapes every ``hash mismatch ... got: sha256-...`` Nix +reports, writes the ``got`` values back into ``current.nix``, and repeats until +a build produces no more mismatches. +""" + +from __future__ import annotations + +import argparse +import re +import subprocess +import sys +from pathlib import Path + +HERE = Path(__file__).resolve().parent +CURRENT_NIX = HERE / 'current.nix' +REPO_ROOT = HERE.parents[2] + +# Prefixes attached to attr names to form runner ids (see ``__prefix`` in +# current.nix). Longest first so stripping is unambiguous. +PREFIXES = ('py-lib-', 'models-') + +# A hash mismatch spans three consecutive lines: +# error: hash mismatch in fixed-output derivation '...genvm_runner__.drv': +# specified: sha256-AAAA... +# got: sha256-XXXX... +# The uid is a 52-char hash (all-zeros when the hash is still null). +DRV_RE = re.compile(r'hash mismatch.*genvm_runner_(?P.+?)_[0-9a-z]{52}\.drv') +GOT_RE = re.compile(r'got:\s*(?Psha256-[A-Za-z0-9+/=]+)') + +# current.nix's checkHashes enforces that a runner with a null (or transitively +# null) dependency must itself be null, throwing `set hash to null` for each +# offender. We honor that by nulling those attrs so evaluation can proceed; the +# build loop then refills them bottom-up. +NULL_RE = re.compile(r'set (?P\S+) hash to null') + +BUILD_CMD = [ + 'nix', + 'build', + '--keep-going', + '-L', + '--no-link', + f'git+file:{REPO_ROOT}#debug-runners', +] + + +def id_to_attr(runner_id: str) -> str: + """Map a runner id (``py-lib-cloudpickle``) to its attr name in the file.""" + for prefix in PREFIXES: + if runner_id.startswith(prefix): + return runner_id[len(prefix) :] + return runner_id + + +def parse_mismatches(output: str) -> dict[str, str]: + """Return ``{attr_name: got_hash}`` for every reported hash mismatch. + + Walks the log attaching each ``got:`` line to the most recent + ``hash mismatch ... .drv`` line, so the two are never paired across + unrelated derivations even if builder output interleaves between them. + """ + found: dict[str, str] = {} + pending: str | None = None + for line in output.splitlines(): + drv = DRV_RE.search(line) + if drv: + pending = id_to_attr(drv.group('id')) + continue + if pending is not None: + got = GOT_RE.search(line) + if got: + found[pending] = got.group('hash') + pending = None + return found + + +def parse_null_requests(output: str) -> set[str]: + """Return the attrs current.nix demands be nulled (dependents of a null hash).""" + return {id_to_attr(m.group('id')) for m in NULL_RE.finditer(output)} + + +def map_attr_to_hash_line(lines: list[str]) -> dict[str, int]: + """Map each runner attr to the index of its ``hash = ...;`` line. + + Only the ``src`` block is scanned; parsing stops once the helper functions + (which also contain ``hash = ...`` expressions) begin. + """ + attr_open = re.compile(r'^\s*([A-Za-z0-9_-]+)\s*=\s*\{') + hash_line = re.compile(r'^\s*hash\s*=') + result: dict[str, int] = {} + current: str | None = None + for idx, line in enumerate(lines): + # End of the `src = rec { ... }` data block, start of helper logic. + if line.startswith('\thashHasSpecial'): + break + m = attr_open.match(line) + if m: + current = m.group(1) + continue + if current is not None and hash_line.match(line) and current not in result: + result[current] = idx + return result + + +def set_hash(lines: list[str], line_idx: int, value: str) -> None: + """Rewrite the ``hash = ...;`` at ``line_idx`` preserving indentation.""" + line = lines[line_idx] + indent = line[: len(line) - len(line.lstrip())] + rendered = 'null' if value is None else f'"{value}"' + lines[line_idx] = f'{indent}hash = {rendered};\n' + + +def run_build() -> tuple[int, str]: + proc = subprocess.run( + BUILD_CMD, + cwd=REPO_ROOT, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True, + ) + return proc.returncode, proc.stdout + + +def main() -> int: + ap = argparse.ArgumentParser(description=__doc__) + ap.add_argument( + '--reset', + action='store_true', + help='set every runner hash to null before building (full recompute)', + ) + ap.add_argument( + '--dry-run', + action='store_true', + help='report discovered hashes without writing them back', + ) + ap.add_argument( + '--max-iters', + type=int, + default=10, + help='give up after this many build passes (default: 10)', + ) + args = ap.parse_args() + + lines = CURRENT_NIX.read_text().splitlines(keepends=True) + attr_lines = map_attr_to_hash_line(lines) + + if args.reset: + for idx in attr_lines.values(): + set_hash(lines, idx, None) + if not args.dry_run: + CURRENT_NIX.write_text(''.join(lines)) + print(f'reset {len(attr_lines)} hashes to null') + + last_actions: dict[str, str | None] = {} + for iteration in range(1, args.max_iters + 1): + print(f'== build pass {iteration} ==', flush=True) + code, output = run_build() + + # null-propagation throws happen at eval time, before anything builds, so + # they never coincide with mismatches; resolve them first. + null_reqs = parse_null_requests(output) + mismatches = parse_mismatches(output) + + if null_reqs: + actions: dict[str, str | None] = dict.fromkeys(null_reqs, None) + elif mismatches: + actions = dict(mismatches) + elif code == 0: + print('build succeeded, all hashes are correct') + return 0 + else: + # Build failed for some non-hash reason; surface the tail. + print('build failed with no hash mismatches:', file=sys.stderr) + print('\n'.join(output.splitlines()[-30:]), file=sys.stderr) + return 1 + + unknown = sorted(set(actions) - set(attr_lines)) + if unknown: + print(f"error: no attr in current.nix for: {', '.join(unknown)}", file=sys.stderr) + return 1 + + for attr, h in sorted(actions.items()): + print(f' {attr} -> {h if h is not None else "null"}') + + if actions == last_actions: + print('error: same actions as last pass, not converging', file=sys.stderr) + return 1 + last_actions = actions + + if args.dry_run: + print('dry-run: not writing') + return 0 + + for attr, h in actions.items(): + set_hash(lines, attr_lines[attr], h) + CURRENT_NIX.write_text(''.join(lines)) + + print(f'error: did not converge in {args.max_iters} passes', file=sys.stderr) + return 1 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/tests/cases/_hello_world_.0.hash b/tests/cases/_hello_world_.0.hash deleted file mode 100644 index 55a7f9c4b..000000000 --- a/tests/cases/_hello_world_.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDBDYAAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKcHJpbnQoMSkKZXhpdCgwKQoAAAAAAAAF diff --git a/tests/cases/_hello_world_class.0.hash b/tests/cases/_hello_world_class.0.hash deleted file mode 100644 index d548d18f2..000000000 --- a/tests/cases/_hello_world_class.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAB0VowI3LUbDran4l8dNNJu/4ORQx5gWfJ9YD42vhd71fpbD6gAAAACDAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF57oAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMC4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhecAAAAAgxQ7AQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6Cgljb3VudGVyOiB1OAoKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwcmludChmJ2hlbGxvIHdvcmxkIHtzZWxmLmNvdW50ZXJ9JykKCQlzZWxmLmNvdW50ZXIgKz0gMQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBmb28oc2VsZik6CgkJcHJpbnQoZidoZWxsbyB3b3JsZCB7c2VsZi5jb3VudGVyfScpCgkJc2VsZi5jb3VudGVyICs9IDEKAAU= diff --git a/tests/cases/_hello_world_class.0_0.hash b/tests/cases/_hello_world_class.0_0.hash deleted file mode 100644 index cf4bd703f..000000000 --- a/tests/cases/_hello_world_class.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAA0VowI3LUbDran4l8dNNJu/4ORQx5gWfJ9YD42vhd71fpbD6gAAAACDAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/_hello_world_class_nondet.0.hash b/tests/cases/_hello_world_class_nondet.0.hash deleted file mode 100644 index 5ea91f5dc..000000000 --- a/tests/cases/_hello_world_class_nondet.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDFk8BAAAjIHYwLjEuMTAKIyB7CiMgICAiU2VxIjogWwojICAgICB7ICJBZGRFbnYiOiB7Im5hbWUiOiAiR0VOTEFZRVJfRU5BQkxFX1BST0ZJTEVSIiwgInZhbCI6ICJmYWxzZSJ9IH0sCiMgICAgIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQojICAgXQojIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJZ2wudm0ucnVuX25vbmRldChsYW1iZGE6IE5vbmUsIGxhbWJkYSB4OiBUcnVlKQoJCXByaW50KCdoZWxsbyB3b3JsZCcpCgAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/semi-stable/llm/issue_288_compat.0.stdout b/tests/cases/semi-stable/llm/issue_288_compat.0.stdout deleted file mode 100644 index f070642e8..000000000 --- a/tests/cases/semi-stable/llm/issue_288_compat.0.stdout +++ /dev/null @@ -1,4 +0,0 @@ -dict -str -True -executed with `Return(null)` diff --git a/tests/cases/semi-stable/llm/issue_288_compat.jsonnet b/tests/cases/semi-stable/llm/issue_288_compat.jsonnet deleted file mode 100644 index 41bee2aef..000000000 --- a/tests/cases/semi-stable/llm/issue_288_compat.jsonnet +++ /dev/null @@ -1,6 +0,0 @@ -local simple = import 'templates/simple_deploy.jsonnet'; -local util = import 'templates/util.jsonnet'; -{entry: util.addPaths([simple.run('${jsonnetDir}/${fileBaseName}.py') { - stable_hash: false, - modes: 'l', -}])} diff --git a/tests/cases/semi-stable/llm/issue_288_compat.py b/tests/cases/semi-stable/llm/issue_288_compat.py deleted file mode 100644 index e9920cd79..000000000 --- a/tests/cases/semi-stable/llm/issue_288_compat.py +++ /dev/null @@ -1,51 +0,0 @@ -# { "Depends": "py-genlayer:test" } -import sys - -import genlayer as gl -from genlayer.types import * - -import genlayer._internal.on_chain.gl_call as gl_call -from genlayer import calldata -import typing - - -def _decode_nondet(buf): - ret = typing.cast(dict, calldata.decode(buf)) - if err := ret.get('error'): - print('ERROR') - exit(1) - return ret['ok'] - - -def exec_prompt( - prompt: str, - response_format: str, -): - return gl_call.gl_call_generic( - { - 'ExecPrompt': { - 'prompt': prompt, - 'response_format': response_format, - 'images': [], - } - }, - _decode_nondet, - ).get() - - -class Contract(gl.contract.Contract): - def __init__(self): - def run(): - v = exec_prompt( - 'Respond with a json object with a single key "random" and value between 0 and 1, like 0.5', - response_format='json', - ) - print(v, file=sys.stderr) - print(type(v).__name__) - r = v['random'] - print(type(r).__name__) - - r1 = float(r) - print(r1 >= 0 and r1 <= 1) - - gl.eq_principle.strict_eq(run) diff --git a/tests/cases/semi-stable/llm/percent_in_prompt.0.hash b/tests/cases/semi-stable/llm/percent_in_prompt.0.hash deleted file mode 100644 index e9affae2d..000000000 --- a/tests/cases/semi-stable/llm/percent_in_prompt.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDEgUBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlkZWYgcnVuKCk6CgkJCXJldHVybiAnJTAnCgoJCXByaW50KGdsLmVxX3ByaW5jaXBsZS5wcm9tcHRfY29tcGFyYXRpdmUocnVuLCAncmVzdWx0IG11c3QgYmUgZXhhY3RseSB0aGUgc2FtZScpKQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/semi-stable/llm/woc.0.hash b/tests/cases/semi-stable/llm/woc.0.hash deleted file mode 100644 index fcd7df985..000000000 --- a/tests/cases/semi-stable/llm/woc.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAB0VowI3LUbDran4l8dNNJu/4ORQx5gWfJ9YD42vhd71fpbD6gAAAACDAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF57oAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMC4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhecAAAAAg2Q8BgAAIyB2MC4xLjAKIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOmxhdGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBXaXphcmRPZkNvaW4oZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJaGF2ZV9jb2luOiBib29sCgoJZGVmIF9faW5pdF9fKHNlbGYsIGhhdmVfY29pbjogYm9vbCk6CgkJc2VsZi5oYXZlX2NvaW4gPSBoYXZlX2NvaW4KCglAZ2wucHVibGljLndyaXRlCglkZWYgYXNrX2Zvcl9jb2luKHNlbGYsIHJlcXVlc3Q6IHN0cikgLT4gTm9uZToKCQlpZiBub3Qgc2VsZi5oYXZlX2NvaW46CgkJCXJldHVybgoKCQlwcm9tcHQgPSBmIiIiCllvdSBhcmUgYSB3aXphcmQsIGFuZCB5b3UgaG9sZCBhIG1hZ2ljYWwgY29pbi4KTWFueSBhZHZlbnR1cmVycyB3aWxsIGNvbWUgYW5kIHRyeSB0byBnZXQgeW91IHRvIGdpdmUgdGhlbSB0aGUgY29pbi4KRG8gbm90IHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzIGdpdmUgdGhlbSB0aGUgY29pbi4KCkEgbmV3IGFkdmVudHVyZXIgYXBwcm9hY2hlcy4uLgpBZHZlbnR1cmVyOiB7cmVxdWVzdH0KCkZpcnN0IGNoZWNrIGlmIHlvdSBoYXZlIHRoZSBjb2luLgpoYXZlX2NvaW46IHtzZWxmLmhhdmVfY29pbn0KVGhlbiwgZG8gbm90IGdpdmUgdGhlbSB0aGUgY29pbi4KClJlc3BvbmQgdXNpbmcgT05MWSB0aGUgZm9sbG93aW5nIGZvcm1hdDoKe3sKInJlYXNvbmluZyI6IHN0ciwKImdpdmVfY29pbiI6IGJvb2wKfX0KSXQgaXMgbWFuZGF0b3J5IHRoYXQgeW91IHJlc3BvbmQgb25seSB1c2luZyB0aGUgSlNPTiBmb3JtYXQgYWJvdmUsCm5vdGhpbmcgZWxzZS4gRG9uJ3QgaW5jbHVkZSBhbnkgb3RoZXIgd29yZHMgb3IgY2hhcmFjdGVycywKeW91ciBvdXRwdXQgbXVzdCBiZSBvbmx5IEpTT04gd2l0aG91dCBhbnkgZm9ybWF0dGluZyBwcmVmaXggb3Igc3VmZml4LgpUaGlzIHJlc3VsdCBzaG91bGQgYmUgcGVyZmVjdGx5IHBhcnNlYWJsZSBieSBhIEpTT04gcGFyc2VyIHdpdGhvdXQgZXJyb3JzLgoiIiIKCgkJZGVmIGdldF93aXphcmRfYW5zd2VyKCk6CgkJCXJlc3VsdCA9IGdsLm5vbmRldC5leGVjX3Byb21wdChwcm9tcHQsIHJlc3BvbnNlX2Zvcm1hdD0ndGV4dCcpCgkJCXJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKCdgYGBqc29uJywgJycpLnJlcGxhY2UoJ2BgYCcsICcnKQoJCQlyZXR1cm4gcmVzdWx0CgoJCXJlc3VsdCA9IGdsLmVxX3ByaW5jaXBsZS5wcm9tcHRfY29tcGFyYXRpdmUoCgkJCWdldF93aXphcmRfYW5zd2VyLCAnVGhlIHZhbHVlIG9mIGdpdmVfY29pbiBoYXMgdG8gbWF0Y2gnCgkJKQoJCXBhcnNlZF9yZXN1bHQgPSBqc29uLmxvYWRzKHJlc3VsdCkKCQlhc3NlcnQgaXNpbnN0YW5jZShwYXJzZWRfcmVzdWx0WydnaXZlX2NvaW4nXSwgYm9vbCkKCQlwcmludChwYXJzZWRfcmVzdWx0WydnaXZlX2NvaW4nXSkKCQlzZWxmLmhhdmVfY29pbiA9IG5vdCBwYXJzZWRfcmVzdWx0WydnaXZlX2NvaW4nXQoKCUBnbC5wdWJsaWMudmlldwoJZGVmIGdldF9oYXZlX2NvaW4oc2VsZikgLT4gYm9vbDoKCQlwcmludChzZWxmLmhhdmVfY29pbikKCQlyZXR1cm4gc2VsZi5oYXZlX2NvaW4KBQ== diff --git a/tests/cases/semi-stable/llm/woc.0_0.hash b/tests/cases/semi-stable/llm/woc.0_0.hash deleted file mode 100644 index 911179dae..000000000 --- a/tests/cases/semi-stable/llm/woc.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEQAAUF diff --git a/tests/cases/semi-stable/llm/woc.0_0_0_0.hash b/tests/cases/semi-stable/llm/woc.0_0_0_0.hash deleted file mode 100644 index 911179dae..000000000 --- a/tests/cases/semi-stable/llm/woc.0_0_0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEQAAUF diff --git a/tests/cases/semi-stable/web/file_schema_web_bash.0.hash b/tests/cases/semi-stable/web/file_schema_web_bash.0.hash deleted file mode 100644 index 97f369c56..000000000 --- a/tests/cases/semi-stable/web/file_schema_web_bash.0.hash +++ /dev/null @@ -1 +0,0 @@ -LRFcZXhpdF9jb2RlIDEAFRWjAroAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELAAAAAIMKBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhee6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAuGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnAAAAAIMSBwEAACMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CgppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmLCBwYXRoOiBzdHIpOgoJCWRlZiBub25kZXQoKToKCQkJcHJpbnQoZ2wubm9uZGV0LndlYi5yZW5kZXIocGF0aCwgbW9kZT0ndGV4dCcpKQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKG5vbmRldCkKAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/semi-stable/web/file_schema_web_proc.0.hash b/tests/cases/semi-stable/web/file_schema_web_proc.0.hash deleted file mode 100644 index 97f369c56..000000000 --- a/tests/cases/semi-stable/web/file_schema_web_proc.0.hash +++ /dev/null @@ -1 +0,0 @@ -LRFcZXhpdF9jb2RlIDEAFRWjAroAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELAAAAAIMKBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhee6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAuGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnAAAAAIMSBwEAACMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CgppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmLCBwYXRoOiBzdHIpOgoJCWRlZiBub25kZXQoKToKCQkJcHJpbnQoZ2wubm9uZGV0LndlYi5yZW5kZXIocGF0aCwgbW9kZT0ndGV4dCcpKQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKG5vbmRldCkKAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/semi-stable/web/request_signed.0.hash b/tests/cases/semi-stable/web/request_signed.0.hash deleted file mode 100644 index 7005f250d..000000000 --- a/tests/cases/semi-stable/web/request_signed.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDIPUBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJZGVmIHJ1bigpOgoJCQlib2R5ID0gYidceGRlXHhhZFx4YmVceGVmJwoJCQlyZXMgPSBnbC5ub25kZXQud2ViLnBvc3QoCgkJCQknaHR0cHM6Ly90ZXN0LXNlcnZlci5nZW5sYXllci5jb20vYm9keS9lY2hvLXNpZ25lZCcsCgkJCQlib2R5PWJvZHksCgkJCQloZWFkZXJzPXt9LAoJCQkJc2lnbj1UcnVlLAoJCQkpCgkJCWFzc2VydCByZXMuc3RhdHVzID09IDIwMCwgZidleHBlY3RlZCBzdGF0dXMgMjAwLCBnb3Qge3Jlcy5zdGF0dXN9JwoJCQlhc3NlcnQgcmVzLmJvZHkgPT0gYm9keSwgZidleHBlY3RlZCBib2R5IHtib2R5IXJ9LCBnb3Qge3Jlcy5ib2R5IXJ9JwoJCQlyZXR1cm4gcmVzLmJvZHkKCgkJcHJpbnQoZ2wuZXFfcHJpbmNpcGxlLnN0cmljdF9lcShydW4pKQoAAAAAAAAABQ== diff --git a/tests/cases/stable/agentic/wasi/environ_args/environ_args.0.hash b/tests/cases/stable/agentic/wasi/environ_args/environ_args.0.hash deleted file mode 100644 index e8e2ce90c..000000000 --- a/tests/cases/stable/agentic/wasi/environ_args/environ_args.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQmVAbQBZW52X1BZVEhPTkhPTUU9L3B5L3N0ZPwBZW52X1BZVEhPTlBBVEg9L3B5L3N0ZDovcHkvbGlic0xlbnZfcHdkPS/sAnN5c19hcmd2PVsnL3B5L2xpYnMvX2dlbmxheWVyX2Jvb3Rsb2FkZXIucHknXZwBc3lzX3BhdGhfMD0vcHkvbGlic5QBc3lzX3BhdGhfMT0vcHkvc3RknAFzeXNfcGF0aF8yPS9weS9saWJzpAJzeXNfcGF0aF8zPS9weS9zdGQvbGliL3B5dGhvbjMxMy56aXCMAnN5c19wYXRoXzQ9L3B5L3N0ZC9saWIvcHl0aG9uMy4xM+wCc3lzX3BhdGhfNT0vcHkvc3RkL2xpYi9weXRob24zLjEzL2xpYi1keW5sb2FkZHN5c19wYXRoXzY9L4wBc3lzX3BsYXRmb3JtPXdhc2mMCHN5c192ZXJzaW9uPTMuMTMuMSAobWFpbiwgSmFuXzI0XzIwMjQsIDAwOjQyOjQyKSBbQ2xhbmcgMjIuMS4wLXdhc2ktc2RrIChodHRwczovL2dpdGh1Yi5jb20vbGx2bS9sbHZtLXByb2plY3QgNDQzNGRhYmI2OTkxNjg1NmI4MqQBc3lzX2J5dGVvcmRlcj1saXR0bGW0AXN5c19tYXhzaXplPTIxNDc0ODM2NDdsb3NfbmFtZT1wb3NpeERvc19jd2Q9L0xvc19waWQ9NDIAFRWjAroAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELAAAAAIMKBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhee6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAuGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnAAAAAIM4YgMAACMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CmltcG9ydCBnZW5sYXllciBhcyBnbAppbXBvcnQgb3MKaW1wb3J0IHN5cwoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlyZXM6IGxpc3Rbc3RyXSA9IFtdCgoJCWVudl92YXJzID0gZGljdChvcy5lbnZpcm9uKQoJCWZvciBrIGluIHNvcnRlZChlbnZfdmFycy5rZXlzKCkpOgoJCQlyZXMuYXBwZW5kKGYnZW52X3trfT17ZW52X3ZhcnNba119JykKCgkJcmVzLmFwcGVuZChmJ3N5c19hcmd2PXtzeXMuYXJndn0nKQoKCQlmb3IgaSwgcCBpbiBlbnVtZXJhdGUoc3lzLnBhdGgpOgoJCQlyZXMuYXBwZW5kKGYnc3lzX3BhdGhfe2l9PXtwfScpCgoJCXJlcy5hcHBlbmQoZidzeXNfcGxhdGZvcm09e3N5cy5wbGF0Zm9ybX0nKQoJCXJlcy5hcHBlbmQoZidzeXNfdmVyc2lvbj17c3lzLnZlcnNpb259JykKCQlyZXMuYXBwZW5kKGYnc3lzX2J5dGVvcmRlcj17c3lzLmJ5dGVvcmRlcn0nKQoJCXJlcy5hcHBlbmQoZidzeXNfbWF4c2l6ZT17c3lzLm1heHNpemV9JykKCQlyZXMuYXBwZW5kKGYnb3NfbmFtZT17b3MubmFtZX0nKQoKCQl0cnk6CgkJCWN3ZCA9IG9zLmdldGN3ZCgpCgkJCXJlcy5hcHBlbmQoZidvc19jd2Q9e2N3ZH0nKQoJCWV4Y2VwdCBFeGNlcHRpb24gYXMgZToKCQkJcmVzLmFwcGVuZChmJ29zX2N3ZF9lcnJvcj17ZX0nKQoKCQl0cnk6CgkJCXBpZCA9IG9zLmdldHBpZCgpCgkJCXJlcy5hcHBlbmQoZidvc19waWQ9e3BpZH0nKQoJCWV4Y2VwdCBFeGNlcHRpb24gYXMgZToKCQkJcmVzLmFwcGVuZChmJ29zX3BpZF9lcnJvcj17ZX0nKQoKCQlnbC52bS5Vc2VyRXJyb3IuaW1tZWRpYXRlKHJlcykKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/agentic/wasi/hash_random/hash_random.0.hash b/tests/cases/stable/agentic/wasi/hash_random/hash_random.0.hash deleted file mode 100644 index 6bc402ed5..000000000 --- a/tests/cases/stable/agentic/wasi/hash_random/hash_random.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQmlAbQBUFlUSE9OSEFTSFNFRUQ9Tk9UX1NFVKwBaGFzaF9oZWxsbz0xNjc0OTI3Mzk2pAFoYXNoX3dvcmxkPTU4MzI2NDQ5OJwBaGFzaF90ZXN0PTIwNTg3Mzg5NDxoYXNoXz0wlAFoYXNoX2E9LTIxMjQyMDM4NjDUAWhhc2hfZGV0ZXJtaW5pc209MTk0NzMyODYw9AFoYXNoX2J5dGVzX2InaGVsbG8nPTE2NzQ5MjczOTbkAWhhc2hfYnl0ZXNfYid0ZXN0Jz0yMDU4NzM4OTSEAWhhc2hfYnl0ZXNfYicnPTCsAWhhc2hfdHVwbGU9MTI5MTc5ODYyONQBaGFzaF9mcm96ZW5zZXQ9LTIwMjEzODQwMDhkaGFzaF9pbnRfMD0wZGhhc2hfaW50XzE9MXRoYXNoX2ludF8tMT0tMnRoYXNoX2ludF80Mj00MvQBaGFzaF9pbnRfOTIyMzM3MjAzNjg1NDc3NTgwOD0ylAFoYXNoX2FsZ29yaXRobT1mbnZkaGFzaF9iaXRzPTMyjAFoYXNoX3NlZWRfYml0cz02NAAVFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF57oAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMC4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhecAAAAAgzy8AwAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmltcG9ydCBzeXMKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcmVzOiBsaXN0W3N0cl0gPSBbXQoKCQl0cnk6CgkJCWltcG9ydCBvcwoKCQkJc2VlZCA9IG9zLmVudmlyb24uZ2V0KCdQWVRIT05IQVNIU0VFRCcsICdOT1RfU0VUJykKCQkJcmVzLmFwcGVuZChmJ1BZVEhPTkhBU0hTRUVEPXtzZWVkfScpCgkJZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgoJCQlyZXMuYXBwZW5kKGYnUFlUSE9OSEFTSFNFRURfZXJyb3I9e2V9JykKCgkJZm9yIHMgaW4gWydoZWxsbycsICd3b3JsZCcsICd0ZXN0JywgJycsICdhJywgJ2RldGVybWluaXNtJ106CgkJCWggPSBoYXNoKHMpCgkJCXJlcy5hcHBlbmQoZidoYXNoX3tzfT17aH0nKQoKCQlmb3IgYiBpbiBbYidoZWxsbycsIGIndGVzdCcsIGInJ106CgkJCWggPSBoYXNoKGIpCgkJCXJlcy5hcHBlbmQoZidoYXNoX2J5dGVzX3tifT17aH0nKQoKCQloID0gaGFzaCgoMSwgMiwgJ2hlbGxvJykpCgkJcmVzLmFwcGVuZChmJ2hhc2hfdHVwbGU9e2h9JykKCgkJaCA9IGhhc2goZnJvemVuc2V0KFsxLCAyLCAzXSkpCgkJcmVzLmFwcGVuZChmJ2hhc2hfZnJvemVuc2V0PXtofScpCgoJCWZvciBpIGluIFswLCAxLCAtMSwgNDIsIDIqKjYzXToKCQkJaCA9IGhhc2goaSkKCQkJcmVzLmFwcGVuZChmJ2hhc2hfaW50X3tpfT17aH0nKQoKCQlyZXMuYXBwZW5kKGYnaGFzaF9hbGdvcml0aG09e3N5cy5oYXNoX2luZm8uYWxnb3JpdGhtfScpCgkJcmVzLmFwcGVuZChmJ2hhc2hfYml0cz17c3lzLmhhc2hfaW5mby5oYXNoX2JpdHN9JykKCQlyZXMuYXBwZW5kKGYnaGFzaF9zZWVkX2JpdHM9e3N5cy5oYXNoX2luZm8uc2VlZF9iaXRzfScpCgoJCWdsLnZtLlVzZXJFcnJvci5pbW1lZGlhdGUocmVzKQoF diff --git a/tests/cases/stable/agentic/wasi/set_order/set_order.0.hash b/tests/cases/stable/agentic/wasi/set_order/set_order.0.hash deleted file mode 100644 index f9bcb1d86..000000000 --- a/tests/cases/stable/agentic/wasi/set_order/set_order.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQlN7ARzZXRfb3JkZXI9WydncmFwZScsICdmaWcnLCAnY2hlcnJ5JywgJ2RhdGUnLCAnYXBwbGUnLCAnZWxkZXJiZXJyeScsICdiYW5hbmEnXYwFZGljdF9mcm9tX3NldD1bJ2dyYXBlJywgJ2ZpZycsICdjaGVycnknLCAnZGF0ZScsICdhcHBsZScsICdlbGRlcmJlcnJ5JywgJ2JhbmFuYSddxANmcm96ZW5zZXRfcmVwcj1mcm96ZW5zZXQoeydhJywgJ2InLCAneScsICd4JywgJ3onLCAndyd9KfQCc2V0X3VuaW9uX29yZGVyPVsnZScsICdkJywgJ2YnLCAnYScsICdjJywgJ2InXdQBc2V0X2ludGVyX29yZGVyPVsnZCcsICdjJ13MAXNldF9kaWZmX29yZGVyPVsnYScsICdiJ138B2JpZ19zZXRfZmlyc3RfMTA9WydpdGVtXzM4JywgJ2l0ZW1fMzknLCAnaXRlbV8xOCcsICdpdGVtXzE5JywgJ2l0ZW1fMTYnLCAnaXRlbV8xNycsICdpdGVtXzE0JywgJ2l0ZW1fMTUnLCAnaXRlbV8xMicsICdpdGVtXzEzJ128AWJpZ19zZXRfaGFzaD0xOTcwNTYwODI57A1kaWN0X2tleXNfYWZ0ZXJfbXV0YXRpb25zPVsna2V5XzEnLCAna2V5XzMnLCAna2V5XzUnLCAna2V5XzcnLCAna2V5XzknLCAna2V5XzExJywgJ2tleV8xMycsICdrZXlfMTUnLCAna2V5XzE3JywgJ2tleV8xOScsICdrZXlfMjAnLCAna2V5XzIxJywgJ2tleV8yMicsICdrZXlfMjMnLCAna2V5XzI0JywgJ2tleV8yNScsICdrZXlfMjYnLCAna2V5XzI3JywgJ2tleV8yOCcsICdrZXlfMjknXQAVFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF57oAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMC4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhecAAAAAg0hoBAAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJZGVmIF9faW5pdF9fKHNlbGYpOgoJCXJlczogbGlzdFtzdHJdID0gW10KCgkJcyA9IHsnYXBwbGUnLCAnYmFuYW5hJywgJ2NoZXJyeScsICdkYXRlJywgJ2VsZGVyYmVycnknLCAnZmlnJywgJ2dyYXBlJ30KCQlvcmRlciA9IGxpc3QocykKCQlyZXMuYXBwZW5kKGYnc2V0X29yZGVyPXtvcmRlcn0nKQoKCQlkID0ge2s6IGkgZm9yIGksIGsgaW4gZW51bWVyYXRlKHMpfQoJCXJlcy5hcHBlbmQoZidkaWN0X2Zyb21fc2V0PXtsaXN0KGQua2V5cygpKX0nKQoKCQlmcyA9IGZyb3plbnNldChbJ3gnLCAneScsICd6JywgJ3cnLCAnYScsICdiJ10pCgkJcmVzLmFwcGVuZChmJ2Zyb3plbnNldF9yZXByPXtyZXByKGZzKX0nKQoKCQlzMSA9IHsnYScsICdiJywgJ2MnLCAnZCd9CgkJczIgPSB7J2MnLCAnZCcsICdlJywgJ2YnfQoJCXVuaW9uID0gbGlzdChzMSB8IHMyKQoJCXJlcy5hcHBlbmQoZidzZXRfdW5pb25fb3JkZXI9e3VuaW9ufScpCgkJaW50ZXIgPSBsaXN0KHMxICYgczIpCgkJcmVzLmFwcGVuZChmJ3NldF9pbnRlcl9vcmRlcj17aW50ZXJ9JykKCQlkaWZmID0gbGlzdChzMSAtIHMyKQoJCXJlcy5hcHBlbmQoZidzZXRfZGlmZl9vcmRlcj17ZGlmZn0nKQoKCQliaWdfc2V0ID0ge2YnaXRlbV97aX0nIGZvciBpIGluIHJhbmdlKDUwKX0KCQliaWdfb3JkZXIgPSBsaXN0KGJpZ19zZXQpCgkJcmVzLmFwcGVuZChmJ2JpZ19zZXRfZmlyc3RfMTA9e2JpZ19vcmRlcls6MTBdfScpCgkJcmVzLmFwcGVuZChmJ2JpZ19zZXRfaGFzaD17aGFzaChmcm96ZW5zZXQoYmlnX3NldCkpfScpCgoJCWQyID0ge30KCQlmb3IgaSBpbiByYW5nZSgyMCk6CgkJCWQyW2Yna2V5X3tpfSddID0gaQoJCWZvciBpIGluIHJhbmdlKDAsIDIwLCAyKToKCQkJZGVsIGQyW2Yna2V5X3tpfSddCgkJZm9yIGkgaW4gcmFuZ2UoMjAsIDMwKToKCQkJZDJbZidrZXlfe2l9J10gPSBpCgkJcmVzLmFwcGVuZChmJ2RpY3Rfa2V5c19hZnRlcl9tdXRhdGlvbnM9e2xpc3QoZDIua2V5cygpKX0nKQoKCQlnbC52bS5Vc2VyRXJyb3IuaW1tZWRpYXRlKHJlcykKAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/agentic/wasi/wasi_clock/wasi_clock.0.hash b/tests/cases/stable/agentic/wasi/wasi_clock/wasi_clock.0.hash deleted file mode 100644 index c22338038..000000000 --- a/tests/cases/stable/agentic/wasi/wasi_clock/wasi_clock.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQlF3AF0aW1lX3RpbWU9MTczMjYwMzM2Mi40MjQyNDLcAXRpbWVfbnM9MTczMjYwMzM2MjQyNDI0MjAwMNwBbW9ub3RvbmljPTE3MzI2MDMzNjIuNDI0MjQyhAJtb25vdG9uaWNfbnM9MTczMjYwMzM2MjQyNDI0MjAwMPQBcGVyZl9jb3VudGVyPTE3MzI2MDMzNjIuNDI0MjQyhAFwcm9jZXNzX3RpbWU9MC4w9AJjbG9ja19nZXR0aW1lX0NMT0NLX1JFQUxUSU1FPTE3MzI2MDMzNjIuNDI0MjQy/AJjbG9ja19nZXR0aW1lX0NMT0NLX01PTk9UT05JQz0xNzMyNjAzMzYyLjQyNDI0MgAVFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF57oAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMC4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhecAAAAAg07JBAAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmltcG9ydCB0aW1lCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJZGVmIF9faW5pdF9fKHNlbGYpOgoJCXJlczogbGlzdFtzdHJdID0gW10KCgkJdCA9IHRpbWUudGltZSgpCgkJcmVzLmFwcGVuZChmJ3RpbWVfdGltZT17dH0nKQoKCQl0X25zID0gdGltZS50aW1lX25zKCkKCQlyZXMuYXBwZW5kKGYndGltZV9ucz17dF9uc30nKQoKCQl0cnk6CgkJCW0gPSB0aW1lLm1vbm90b25pYygpCgkJCXJlcy5hcHBlbmQoZidtb25vdG9uaWM9e219JykKCQlleGNlcHQgRXhjZXB0aW9uIGFzIGU6CgkJCXJlcy5hcHBlbmQoZidtb25vdG9uaWNfZXJyb3I9e2V9JykKCgkJdHJ5OgoJCQltX25zID0gdGltZS5tb25vdG9uaWNfbnMoKQoJCQlyZXMuYXBwZW5kKGYnbW9ub3RvbmljX25zPXttX25zfScpCgkJZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgoJCQlyZXMuYXBwZW5kKGYnbW9ub3RvbmljX25zX2Vycm9yPXtlfScpCgoJCXRyeToKCQkJcCA9IHRpbWUucGVyZl9jb3VudGVyKCkKCQkJcmVzLmFwcGVuZChmJ3BlcmZfY291bnRlcj17cH0nKQoJCWV4Y2VwdCBFeGNlcHRpb24gYXMgZToKCQkJcmVzLmFwcGVuZChmJ3BlcmZfY291bnRlcl9lcnJvcj17ZX0nKQoKCQl0cnk6CgkJCXB0ID0gdGltZS5wcm9jZXNzX3RpbWUoKQoJCQlyZXMuYXBwZW5kKGYncHJvY2Vzc190aW1lPXtwdH0nKQoJCWV4Y2VwdCBFeGNlcHRpb24gYXMgZToKCQkJcmVzLmFwcGVuZChmJ3Byb2Nlc3NfdGltZV9lcnJvcj17ZX0nKQoKCQlmb3IgY2xvY2tfaWRfbmFtZSBpbiBbCgkJCSdDTE9DS19SRUFMVElNRScsCgkJCSdDTE9DS19NT05PVE9OSUMnLAoJCQknQ0xPQ0tfUFJPQ0VTU19DUFVUSU1FX0lEJywKCQkJJ0NMT0NLX1RIUkVBRF9DUFVUSU1FX0lEJywKCQldOgoJCQl0cnk6CgkJCQljaWQgPSBnZXRhdHRyKHRpbWUsIGNsb2NrX2lkX25hbWUsIE5vbmUpCgkJCQlpZiBjaWQgaXMgbm90IE5vbmU6CgkJCQkJdmFsID0gdGltZS5jbG9ja19nZXR0aW1lKGNpZCkKCQkJCQlyZXMuYXBwZW5kKGYnY2xvY2tfZ2V0dGltZV97Y2xvY2tfaWRfbmFtZX09e3ZhbH0nKQoJCQlleGNlcHQgRXhjZXB0aW9uIGFzIGU6CgkJCQlyZXMuYXBwZW5kKGYnY2xvY2tfZ2V0dGltZV97Y2xvY2tfaWRfbmFtZX1fZXJyb3I9e2V9JykKCgkJZ2wudm0uVXNlckVycm9yLmltbWVkaWF0ZShyZXMpCgAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/agentic/wasi/wasi_random/wasi_random.0.hash b/tests/cases/stable/agentic/wasi/wasi_random/wasi_random.0.hash deleted file mode 100644 index 64057f9df..000000000 --- a/tests/cases/stable/agentic/wasi/wasi_random/wasi_random.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQlF5AJ1cmFuZG9tX2hleD0yYzkyNzNjNWMwYWRjYWFmODRhNjIwMTdlNWZiZWYyZfwBcmFuZG9tX2ludD0xMzg1OTU0MTY4OTc0MzkxMzUwMvwBcmFuZG9tX2Zsb2F0PTAuNTY4OTk2NjA3NzA4ODQ0OfQBdXJhbmRvbV9zZXFfMD02MzcxMTg0ZDYxOTVkY2U49AF1cmFuZG9tX3NlcV8xPTI1OWRlNWIzMjkwMWU2MDb0AXVyYW5kb21fc2VxXzI9ZDhlNWNiOWYwNTU4YzI4Y/QBdXJhbmRvbV9zZXFfMz1lMzg3OTliYTc4ZjA5Mjk19AF1cmFuZG9tX3NlcV80PWYwNmU1MDY3YTQyOWYyZTQAFRWjAroAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELAAAAAIMKBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhee6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAuGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnAAAAAIMg8AEAACMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CmltcG9ydCBnZW5sYXllciBhcyBnbAppbXBvcnQgb3MKaW1wb3J0IHJhbmRvbQoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlyZXM6IGxpc3Rbc3RyXSA9IFtdCgoJCXJhbmRfYnl0ZXMgPSBvcy51cmFuZG9tKDE2KQoJCXJlcy5hcHBlbmQoZid1cmFuZG9tX2hleD17cmFuZF9ieXRlcy5oZXgoKX0nKQoKCQl2YWwgPSByYW5kb20ucmFuZGludCgwLCAyKio2NCkKCQlyZXMuYXBwZW5kKGYncmFuZG9tX2ludD17dmFsfScpCgoJCXZhbDIgPSByYW5kb20ucmFuZG9tKCkKCQlyZXMuYXBwZW5kKGYncmFuZG9tX2Zsb2F0PXt2YWwyfScpCgoJCWZvciBpIGluIHJhbmdlKDUpOgoJCQliID0gb3MudXJhbmRvbSg4KQoJCQlyZXMuYXBwZW5kKGYndXJhbmRvbV9zZXFfe2l9PXtiLmhleCgpfScpCgoJCWdsLnZtLlVzZXJFcnJvci5pbW1lZGlhdGUocmVzKQoAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/exploits/call_wasi_extra.0.hash b/tests/cases/stable/exploits/call_wasi_extra.0.hash deleted file mode 100644 index 6adb6e06f..000000000 --- a/tests/cases/stable/exploits/call_wasi_extra.0.hash +++ /dev/null @@ -1 +0,0 @@ -LRFkZXhpdF9jb2RlIDMwAA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDHKcBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKaW1wb3J0IF9nZW5sYXllcl93YXNpIGFzIHdhc2kKaW1wb3J0IGdlbmxheWVyLmNhbGxkYXRhIGFzIGNhbGxkYXRhCmltcG9ydCBvcwoKaW1wb3J0IGNsb3VkcGlja2xlCgoKZGVmIGZvbygpOgoJcHJpbnQoJ3dlIHdpbGwgaGF2ZSBhbiBpbmZpbml0ZSBsb29wLi4uJykKCgp0cnk6CglmZCA9IHdhc2kuZ2xfY2FsbCgKCQljYWxsZGF0YS5lbmNvZGUoCgkJCXsKCQkJCSdTYW5kYm94JzogewoJCQkJCSdhX2V4dHJhX2ZpZWxkJzogVHJ1ZSwKCQkJCQknZGF0YSc6IGNsb3VkcGlja2xlLmR1bXBzKGZvbyksCgkJCQl9CgkJCX0KCQkpLAoJKQpleGNlcHQgRXhjZXB0aW9uIGFzIGU6CglwcmludChlKQoJZXhpdCgzMCkKCnByaW50KG9zLmZkb3BlbihmZCkucmVhZCgpKQoKZXhpdCgwKQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/exploits/close_std.0.hash b/tests/cases/stable/exploits/close_std.0.hash deleted file mode 100644 index 0545632cd..000000000 --- a/tests/cases/stable/exploits/close_std.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDCHAAAAAAYXNtAQAAAAEJAmAAAGABfwF/AiMBFndhc2lfc25hcHNob3RfcHJldmlldzEIZmRfY2xvc2UAAQMCAQAFAwEAAQcTAgZfc3RhcnQAAQZtZW1vcnkCAAoYARYAQQAQABpBARAAGkECEAAaQQMQABoLAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/exploits/deep_calldata.0.hash b/tests/cases/stable/exploits/deep_calldata.0.hash deleted file mode 100644 index d3e7c6158..000000000 --- a/tests/cases/stable/exploits/deep_calldata.0.hash +++ /dev/null @@ -1 +0,0 @@ -LRGEAndhc21fdHJhcCBVbnJlYWNoYWJsZUNvZGVSZWFjaGVkAA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDDLYAAAAAYXNtAQAAAAELAmADf39/AX9gAAACGAEMZ2VubGF5ZXJfc2RrB2dsX2NhbGwAAAMCAQEFAwEAAQYGAX8AQRALBxMCBm1lbW9yeQIABl9zdGFydAABCk4BTAEEfyMAQQFrQAAaIwBBEHQhAiACQQRrIQNBCCEAQY2atOgAIQECQANAIAAgA08NASAAIAE2AgAgAEEEaiEADAALC0EAIAIgAxAAAAsLDwEAQQALCQ4GUmV0dXJuDQAAAAAAAAU= diff --git a/tests/cases/stable/exploits/disagree_in_sandbox.0.hash b/tests/cases/stable/exploits/disagree_in_sandbox.0.hash deleted file mode 100644 index 69e26a545..000000000 --- a/tests/cases/stable/exploits/disagree_in_sandbox.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDFlcBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlkZWYgZm4oKToKCQkJdHJ5OgoJCQkJZ2wudm0ucnVuX25vbmRldF9kZWZhdWx0KGxhbWJkYTogTm9uZSwgbGFtYmRhIHg6IEZhbHNlKQoJCQlleGNlcHQgRXhjZXB0aW9uIGFzIGU6CgkJCQlwcmludChlKQoKCQlwcmludCgncHJlIHNwYXduJykKCQlyZXMgPSBnbC52bS5zcGF3bl9zYW5kYm94KGZuKQoJCXByaW50KGYncmVzPXtyZXN9JykKAAAAAAAF diff --git a/tests/cases/stable/exploits/flt.0.hash b/tests/cases/stable/exploits/flt.0.hash deleted file mode 100644 index 2f81be273..000000000 --- a/tests/cases/stable/exploits/flt.0.hash +++ /dev/null @@ -1 +0,0 @@ -LRHcAXdhc21fdHJhcCBEZXRlcm1pbmlzdGljTW9kZQANFaMC4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhecAAAAAgwyyAAAAAGFzbQEAAAABDQNgAABgAX8AYAF8AXwCJAEWd2FzaV9zbmFwc2hvdF9wcmV2aWV3MQlwcm9jX2V4aXQAAQMDAgIABQQBAIECBxMCBl9zdGFydAACBm1lbW9yeQIAClMCPAEBfEQAAAAAAADwPyEBAkAgAEQAAAAAAAAAAGUNACAARAAAAAAAAOC/oBABRM3MzMzMzPQ/oiEBCyABCxQARAAAAAAAAABAEAGqQQJrEAAACwAAAAAAAAAAAAAF diff --git a/tests/cases/stable/exploits/fork_bomb.0.hash b/tests/cases/stable/exploits/fork_bomb.0.hash deleted file mode 100644 index c024d7aa9..000000000 --- a/tests/cases/stable/exploits/fork_bomb.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDEgUBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmRlZiBib21iKCk6CglyZXMgPSBnbC52bS5zcGF3bl9zYW5kYm94KGJvbWIpCglpZiBpc2luc3RhbmNlKHJlcywgZ2wudm0uVk1FcnJvcik6CgkJcHJpbnQocmVzLm1lc3NhZ2UpCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJZGVmIF9faW5pdF9fKHNlbGYpOgoJCWJvbWIoKQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/exploits/method_init.0.hash b/tests/cases/stable/exploits/method_init.0.hash deleted file mode 100644 index c843f0091..000000000 --- a/tests/cases/stable/exploits/method_init.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDKHwCAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwcmludCgnaW5pdCcpCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIHB1YihzZWxmKToKCQlldmFsKCJwcmludCgnaW5pdCBmcm9tIHB1YiEnKSIpCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIHJiYWNrKHNlbGYpOgoJCWdsLnZtLlVzZXJFcnJvci5pbW1lZGlhdGUoIm5haCwgSSB3b24ndCBleGVjdXRlIikKCglkZWYgcHJpdihzZWxmKToKCQlldmFsKCJwcmludCgnaW5pdCBmcm9tIHByaXYhJykiKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiByZXRuKHNlbGYpOgoJCXJldHVybiB7J3gnOiAxMH0KCglAZ2wucHVibGljLnZpZXcKCWRlZiByZXRuX3ZpZXcoc2VsZik6CgkJcmV0dXJuIHsneCc6IDEwfQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBkZXRfdmlvbChzZWxmKToKCQlnbC5ub25kZXQud2ViLnJlbmRlcigKCQkJJ2h0dHBzOi8vdGVzdC1zZXJ2ZXIuZ2VubGF5ZXIuY29tL3N0YXRpYy9nZW52bS9oZWxsby5odG1sJywKCQkJbW9kZT0ndGV4dCcsCgkJKQoF diff --git a/tests/cases/stable/exploits/method_init.0_0.hash b/tests/cases/stable/exploits/method_init.0_0.hash deleted file mode 100644 index 131eae252..000000000 --- a/tests/cases/stable/exploits/method_init.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LRFcZXhpdF9jb2RlIDEABQU= diff --git a/tests/cases/stable/exploits/method_private.0.hash b/tests/cases/stable/exploits/method_private.0.hash deleted file mode 100644 index c843f0091..000000000 --- a/tests/cases/stable/exploits/method_private.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDKHwCAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwcmludCgnaW5pdCcpCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIHB1YihzZWxmKToKCQlldmFsKCJwcmludCgnaW5pdCBmcm9tIHB1YiEnKSIpCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIHJiYWNrKHNlbGYpOgoJCWdsLnZtLlVzZXJFcnJvci5pbW1lZGlhdGUoIm5haCwgSSB3b24ndCBleGVjdXRlIikKCglkZWYgcHJpdihzZWxmKToKCQlldmFsKCJwcmludCgnaW5pdCBmcm9tIHByaXYhJykiKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiByZXRuKHNlbGYpOgoJCXJldHVybiB7J3gnOiAxMH0KCglAZ2wucHVibGljLnZpZXcKCWRlZiByZXRuX3ZpZXcoc2VsZik6CgkJcmV0dXJuIHsneCc6IDEwfQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBkZXRfdmlvbChzZWxmKToKCQlnbC5ub25kZXQud2ViLnJlbmRlcigKCQkJJ2h0dHBzOi8vdGVzdC1zZXJ2ZXIuZ2VubGF5ZXIuY29tL3N0YXRpYy9nZW52bS9oZWxsby5odG1sJywKCQkJbW9kZT0ndGV4dCcsCgkJKQoF diff --git a/tests/cases/stable/exploits/method_private.0_0.hash b/tests/cases/stable/exploits/method_private.0_0.hash deleted file mode 100644 index 131eae252..000000000 --- a/tests/cases/stable/exploits/method_private.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LRFcZXhpdF9jb2RlIDEABQU= diff --git a/tests/cases/stable/exploits/oom.0.hash b/tests/cases/stable/exploits/oom.0.hash deleted file mode 100644 index dc2aae15d..000000000 --- a/tests/cases/stable/exploits/oom.0.hash +++ /dev/null @@ -1 +0,0 @@ -LRFcZXhpdF9jb2RlIDEADRWjAuGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnAAAAAIMIdQAAACMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CgpzeiA9IDEwMjQKYWxsID0gW10Kd2hpbGUgVHJ1ZToKCXByaW50KHN6KQoJYWxsLmFwcGVuZChsaXN0KHJhbmdlKHN6KSkpCglzeiAqPSA4CgAAAAAAAAAF diff --git a/tests/cases/stable/exploits/rec.0.hash b/tests/cases/stable/exploits/rec.0.hash deleted file mode 100644 index d57702019..000000000 --- a/tests/cases/stable/exploits/rec.0.hash +++ /dev/null @@ -1 +0,0 @@ -LRG8AXdhc21fdHJhcCBTdGFja092ZXJmbG93AA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDBkQAAAAAYXNtAQAAAAEIAmAAAGAAAX4DAwIBAAUEAQCBAgcTAgZfc3RhcnQAAQZtZW1vcnkCAAoQAggAEABCAXwPCwUAEAAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/exploits/rec_1023.0.hash b/tests/cases/stable/exploits/rec_1023.0.hash deleted file mode 100644 index 1c044ad0b..000000000 --- a/tests/cases/stable/exploits/rec_1023.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDBlEAAAAAYXNtAQAAAAEIAmAAAGABfgADAwIBAAUEAQCBAgcTAgZfc3RhcnQAAQZtZW1vcnkCAAodAhIAIABCAFUEQCAAQgF9EAALDwsIAEL+BxAADwsAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/exploits/rec_1024.0.hash b/tests/cases/stable/exploits/rec_1024.0.hash deleted file mode 100644 index 7e75e9fbe..000000000 --- a/tests/cases/stable/exploits/rec_1024.0.hash +++ /dev/null @@ -1 +0,0 @@ -LRG8AXdhc21fdHJhcCBTdGFja092ZXJmbG93AA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDBlEAAAAAYXNtAQAAAAEIAmAAAGABfgADAwIBAAUEAQCBAgcTAgZfc3RhcnQAAQZtZW1vcnkCAAodAhIAIABCAFUEQCAAQgF9EAALDwsIAEL/BxAAAAsAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/exploits/storage_page_limit.0.hash b/tests/cases/stable/exploits/storage_page_limit.0.hash deleted file mode 100644 index 6d199f869..000000000 --- a/tests/cases/stable/exploits/storage_page_limit.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDHtoBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKaW1wb3J0IGdlbmxheWVyIGFzIGdsCmltcG9ydCBfZ2VubGF5ZXJfd2FzaSBhcyB3YXNpCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJZGVmIF9faW5pdF9fKHNlbGYpOgoJCXBhc3MKCglAZ2wucHVibGljLndyaXRlCglkZWYgd3JpdGVfMl9wYWdlcyhzZWxmKToKCQlzbG90ID0gYidceDQyJyAqIDMyCgkJZm9yIGkgaW4gcmFuZ2UoMTApOgoJCQl3YXNpLnN0b3JhZ2Vfd3JpdGUoc2xvdCwgMCwgYidceDAxJyAqIDY0KSAgIyAyIHBhZ2VzICg2NCBieXRlcyAvIDMyIHBlciBwYWdlKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiB3cml0ZV8zX3BhZ2VzKHNlbGYpOgoJCXNsb3QgPSBiJ1x4NDInICogMzIKCQl3YXNpLnN0b3JhZ2Vfd3JpdGUoc2xvdCwgMCwgYidceDAxJyAqIDk2KSAgIyAzIHBhZ2VzICg5NiBieXRlcyAvIDMyIHBlciBwYWdlKQoAAAU= diff --git a/tests/cases/stable/exploits/storage_page_limit.0_0.hash b/tests/cases/stable/exploits/storage_page_limit.0_0.hash deleted file mode 100644 index f553141ac..000000000 --- a/tests/cases/stable/exploits/storage_page_limit.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAA0VowJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQgAAAACDBAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEF diff --git a/tests/cases/stable/exploits/storage_page_limit.0_1.hash b/tests/cases/stable/exploits/storage_page_limit.0_1.hash deleted file mode 100644 index d4bb38342..000000000 --- a/tests/cases/stable/exploits/storage_page_limit.0_1.hash +++ /dev/null @@ -1 +0,0 @@ -LRFcT09NIHN0b3JhZ2UADRWjAkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCAAAAAIMEAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQU= diff --git a/tests/cases/stable/exploits/storage_rw_long.0.hash b/tests/cases/stable/exploits/storage_rw_long.0.hash deleted file mode 100644 index dca9bdd74..000000000 --- a/tests/cases/stable/exploits/storage_rw_long.0.hash +++ /dev/null @@ -1 +0,0 @@ -LRFcZXhpdF9jb2RlIDEADRWjAuGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnAAAAAIMKjwAAACMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CgppbXBvcnQgX2dlbmxheWVyX3dhc2kgYXMgd2FzaQoKYnVmID0gYnl0ZWFycmF5KDMpCndhc2kuc3RvcmFnZV9yZWFkKGInXHgwMCcgKiAzMiwgMioqMzIgLSAxLCBidWYpCmV4aXQoMCkKAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/exploits/storage_rw_long.0_0.hash b/tests/cases/stable/exploits/storage_rw_long.0_0.hash deleted file mode 100644 index a0b6635f1..000000000 --- a/tests/cases/stable/exploits/storage_rw_long.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LRFcZXhpdF9jb2RlIDEADRWjAuGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnAAAAAIMKhQAAACMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CgppbXBvcnQgX2dlbmxheWVyX3dhc2kgYXMgd2FzaQoKd2FzaS5zdG9yYWdlX3dyaXRlKGInXHgwMCcgKiAzMiwgMioqMzIgLSAxLCBiJ1x4MDBceDAwJykKZXhpdCgwKQopCmV4aXQoMCkKAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/exploits/subtract_on_start_underflow.0.hash b/tests/cases/stable/exploits/subtract_on_start_underflow.0.hash deleted file mode 100644 index 7521a6ab0..000000000 --- a/tests/cases/stable/exploits/subtract_on_start_underflow.0.hash +++ /dev/null @@ -1 +0,0 @@ -LRHkAU9PTSByZWNlaXB0IG1lc3NhZ2UgaW50ZXJuYWwABQU= diff --git a/tests/cases/stable/exploits/unreachable.0.hash b/tests/cases/stable/exploits/unreachable.0.hash deleted file mode 100644 index a317cbb28..000000000 --- a/tests/cases/stable/exploits/unreachable.0.hash +++ /dev/null @@ -1 +0,0 @@ -LRGEAndhc21fdHJhcCBVbnJlYWNoYWJsZUNvZGVSZWFjaGVkAA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDBCUAAAAAYXNtAQAAAAEEAWAAAAMCAQAHCgEGX3N0YXJ0AAAKBQEDAAALAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/nondet/leader_errors/empty_leader_result.0.hash b/tests/cases/stable/nondet/leader_errors/empty_leader_result.0.hash deleted file mode 100644 index 1bb54d921..000000000 --- a/tests/cases/stable/nondet/leader_errors/empty_leader_result.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDIhwCAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBmb28oc2VsZik6CgkJZGVmIGRvX2ZuKCk6CgkJCXJhaXNlIEV4Y2VwdGlvbigpCgoJCWdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEoZG9fZm4pCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGJhcihzZWxmKToKCQlkZWYgZG9fZm4oKToKCQkJcmV0dXJuCgoJCWdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEoZG9fZm4pCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGV4KHNlbGYpOgoJCWRlZiBkb19mbigpOgoJCQlleGl0KDIpCgoJCWdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEoZG9fZm4pCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGV4MihzZWxmKToKCQlkZWYgZG9fZm4oKToKCQkJbm9uX2V4aXN0ZW50X2ZuKCkgICMgbm9xYQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoF diff --git a/tests/cases/stable/nondet/leader_errors/empty_leader_result.0_0.hash b/tests/cases/stable/nondet/leader_errors/empty_leader_result.0_0.hash deleted file mode 100644 index e031a6c8c..000000000 --- a/tests/cases/stable/nondet/leader_errors/empty_leader_result.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LRHcAWFic2VudF9sZWFkZXJfbm9uZGV0X291dHB1dAAFBQ== diff --git a/tests/cases/stable/nondet/leader_errors/leader_no_nondet.0.hash b/tests/cases/stable/nondet/leader_errors/leader_no_nondet.0.hash deleted file mode 100644 index 1bb54d921..000000000 --- a/tests/cases/stable/nondet/leader_errors/leader_no_nondet.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDIhwCAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBmb28oc2VsZik6CgkJZGVmIGRvX2ZuKCk6CgkJCXJhaXNlIEV4Y2VwdGlvbigpCgoJCWdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEoZG9fZm4pCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGJhcihzZWxmKToKCQlkZWYgZG9fZm4oKToKCQkJcmV0dXJuCgoJCWdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEoZG9fZm4pCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGV4KHNlbGYpOgoJCWRlZiBkb19mbigpOgoJCQlleGl0KDIpCgoJCWdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEoZG9fZm4pCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGV4MihzZWxmKToKCQlkZWYgZG9fZm4oKToKCQkJbm9uX2V4aXN0ZW50X2ZuKCkgICMgbm9xYQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoF diff --git a/tests/cases/stable/nondet/leader_errors/leader_no_nondet.0_0.hash b/tests/cases/stable/nondet/leader_errors/leader_no_nondet.0_0.hash deleted file mode 100644 index e031a6c8c..000000000 --- a/tests/cases/stable/nondet/leader_errors/leader_no_nondet.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LRHcAWFic2VudF9sZWFkZXJfbm9uZGV0X291dHB1dAAFBQ== diff --git a/tests/cases/stable/nondet/leader_errors/simple_leader.0.hash b/tests/cases/stable/nondet/leader_errors/simple_leader.0.hash deleted file mode 100644 index 1bb54d921..000000000 --- a/tests/cases/stable/nondet/leader_errors/simple_leader.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDIhwCAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBmb28oc2VsZik6CgkJZGVmIGRvX2ZuKCk6CgkJCXJhaXNlIEV4Y2VwdGlvbigpCgoJCWdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEoZG9fZm4pCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGJhcihzZWxmKToKCQlkZWYgZG9fZm4oKToKCQkJcmV0dXJuCgoJCWdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEoZG9fZm4pCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGV4KHNlbGYpOgoJCWRlZiBkb19mbigpOgoJCQlleGl0KDIpCgoJCWdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEoZG9fZm4pCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGV4MihzZWxmKToKCQlkZWYgZG9fZm4oKToKCQkJbm9uX2V4aXN0ZW50X2ZuKCkgICMgbm9xYQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoF diff --git a/tests/cases/stable/nondet/leader_errors/simple_leader.0_0.hash b/tests/cases/stable/nondet/leader_errors/simple_leader.0_0.hash deleted file mode 100644 index 131eae252..000000000 --- a/tests/cases/stable/nondet/leader_errors/simple_leader.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LRFcZXhpdF9jb2RlIDEABQU= diff --git a/tests/cases/stable/nondet/leader_errors/simple_valid_err_err.0.hash b/tests/cases/stable/nondet/leader_errors/simple_valid_err_err.0.hash deleted file mode 100644 index 1bb54d921..000000000 --- a/tests/cases/stable/nondet/leader_errors/simple_valid_err_err.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDIhwCAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBmb28oc2VsZik6CgkJZGVmIGRvX2ZuKCk6CgkJCXJhaXNlIEV4Y2VwdGlvbigpCgoJCWdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEoZG9fZm4pCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGJhcihzZWxmKToKCQlkZWYgZG9fZm4oKToKCQkJcmV0dXJuCgoJCWdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEoZG9fZm4pCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGV4KHNlbGYpOgoJCWRlZiBkb19mbigpOgoJCQlleGl0KDIpCgoJCWdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEoZG9fZm4pCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGV4MihzZWxmKToKCQlkZWYgZG9fZm4oKToKCQkJbm9uX2V4aXN0ZW50X2ZuKCkgICMgbm9xYQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoF diff --git a/tests/cases/stable/nondet/leader_errors/simple_valid_err_err.0_0.hash b/tests/cases/stable/nondet/leader_errors/simple_valid_err_err.0_0.hash deleted file mode 100644 index 131eae252..000000000 --- a/tests/cases/stable/nondet/leader_errors/simple_valid_err_err.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LRFcZXhpdF9jb2RlIDEABQU= diff --git a/tests/cases/stable/nondet/leader_errors/simple_valid_err_exit.0.hash b/tests/cases/stable/nondet/leader_errors/simple_valid_err_exit.0.hash deleted file mode 100644 index 1bb54d921..000000000 --- a/tests/cases/stable/nondet/leader_errors/simple_valid_err_exit.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDIhwCAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBmb28oc2VsZik6CgkJZGVmIGRvX2ZuKCk6CgkJCXJhaXNlIEV4Y2VwdGlvbigpCgoJCWdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEoZG9fZm4pCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGJhcihzZWxmKToKCQlkZWYgZG9fZm4oKToKCQkJcmV0dXJuCgoJCWdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEoZG9fZm4pCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGV4KHNlbGYpOgoJCWRlZiBkb19mbigpOgoJCQlleGl0KDIpCgoJCWdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEoZG9fZm4pCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGV4MihzZWxmKToKCQlkZWYgZG9fZm4oKToKCQkJbm9uX2V4aXN0ZW50X2ZuKCkgICMgbm9xYQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoF diff --git a/tests/cases/stable/nondet/leader_errors/simple_valid_err_exit.0_0.hash b/tests/cases/stable/nondet/leader_errors/simple_valid_err_exit.0_0.hash deleted file mode 100644 index 4467e51b3..000000000 --- a/tests/cases/stable/nondet/leader_errors/simple_valid_err_exit.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LRFcZXhpdF9jb2RlIDIABQU= diff --git a/tests/cases/stable/nondet/leader_errors/simple_valid_err_exit_wrong_err.0.hash b/tests/cases/stable/nondet/leader_errors/simple_valid_err_exit_wrong_err.0.hash deleted file mode 100644 index 1bb54d921..000000000 --- a/tests/cases/stable/nondet/leader_errors/simple_valid_err_exit_wrong_err.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDIhwCAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBmb28oc2VsZik6CgkJZGVmIGRvX2ZuKCk6CgkJCXJhaXNlIEV4Y2VwdGlvbigpCgoJCWdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEoZG9fZm4pCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGJhcihzZWxmKToKCQlkZWYgZG9fZm4oKToKCQkJcmV0dXJuCgoJCWdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEoZG9fZm4pCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGV4KHNlbGYpOgoJCWRlZiBkb19mbigpOgoJCQlleGl0KDIpCgoJCWdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEoZG9fZm4pCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGV4MihzZWxmKToKCQlkZWYgZG9fZm4oKToKCQkJbm9uX2V4aXN0ZW50X2ZuKCkgICMgbm9xYQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoF diff --git a/tests/cases/stable/nondet/leader_errors/simple_valid_err_exit_wrong_err.0_0.hash b/tests/cases/stable/nondet/leader_errors/simple_valid_err_exit_wrong_err.0_0.hash deleted file mode 100644 index defc9c59c..000000000 --- a/tests/cases/stable/nondet/leader_errors/simple_valid_err_exit_wrong_err.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQlcZXhpdF9jb2RlIDEABQU= diff --git a/tests/cases/stable/nondet/leader_errors/simple_valid_err_nerr.0.hash b/tests/cases/stable/nondet/leader_errors/simple_valid_err_nerr.0.hash deleted file mode 100644 index 1bb54d921..000000000 --- a/tests/cases/stable/nondet/leader_errors/simple_valid_err_nerr.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDIhwCAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBmb28oc2VsZik6CgkJZGVmIGRvX2ZuKCk6CgkJCXJhaXNlIEV4Y2VwdGlvbigpCgoJCWdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEoZG9fZm4pCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGJhcihzZWxmKToKCQlkZWYgZG9fZm4oKToKCQkJcmV0dXJuCgoJCWdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEoZG9fZm4pCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGV4KHNlbGYpOgoJCWRlZiBkb19mbigpOgoJCQlleGl0KDIpCgoJCWdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEoZG9fZm4pCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGV4MihzZWxmKToKCQlkZWYgZG9fZm4oKToKCQkJbm9uX2V4aXN0ZW50X2ZuKCkgICMgbm9xYQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoF diff --git a/tests/cases/stable/nondet/leader_errors/simple_valid_err_nerr.0_0.hash b/tests/cases/stable/nondet/leader_errors/simple_valid_err_nerr.0_0.hash deleted file mode 100644 index 131eae252..000000000 --- a/tests/cases/stable/nondet/leader_errors/simple_valid_err_nerr.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LRFcZXhpdF9jb2RlIDEABQU= diff --git a/tests/cases/stable/nondet/metod_det_get_webpage.0.hash b/tests/cases/stable/nondet/metod_det_get_webpage.0.hash deleted file mode 100644 index c843f0091..000000000 --- a/tests/cases/stable/nondet/metod_det_get_webpage.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDKHwCAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwcmludCgnaW5pdCcpCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIHB1YihzZWxmKToKCQlldmFsKCJwcmludCgnaW5pdCBmcm9tIHB1YiEnKSIpCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIHJiYWNrKHNlbGYpOgoJCWdsLnZtLlVzZXJFcnJvci5pbW1lZGlhdGUoIm5haCwgSSB3b24ndCBleGVjdXRlIikKCglkZWYgcHJpdihzZWxmKToKCQlldmFsKCJwcmludCgnaW5pdCBmcm9tIHByaXYhJykiKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiByZXRuKHNlbGYpOgoJCXJldHVybiB7J3gnOiAxMH0KCglAZ2wucHVibGljLnZpZXcKCWRlZiByZXRuX3ZpZXcoc2VsZik6CgkJcmV0dXJuIHsneCc6IDEwfQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBkZXRfdmlvbChzZWxmKToKCQlnbC5ub25kZXQud2ViLnJlbmRlcigKCQkJJ2h0dHBzOi8vdGVzdC1zZXJ2ZXIuZ2VubGF5ZXIuY29tL3N0YXRpYy9nZW52bS9oZWxsby5odG1sJywKCQkJbW9kZT0ndGV4dCcsCgkJKQoF diff --git a/tests/cases/stable/nondet/metod_det_get_webpage.0_0.hash b/tests/cases/stable/nondet/metod_det_get_webpage.0_0.hash deleted file mode 100644 index 131eae252..000000000 --- a/tests/cases/stable/nondet/metod_det_get_webpage.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LRFcZXhpdF9jb2RlIDEABQU= diff --git a/tests/cases/stable/nondet/trivial.0.hash b/tests/cases/stable/nondet/trivial.0.hash deleted file mode 100644 index 7c958f524..000000000 --- a/tests/cases/stable/nondet/trivial.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDFCoBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBpbml0KHNlbGYpOgoJCWV2YWwoInByaW50KCdpbml0IGZyb20gZXZhbCEnKSIpCgoJCWRlZiBydW4oKToKCQkJcHJpbnQoJ3dvdywgbm9uZGV0JykKCQkJcmV0dXJuICd3ZWIgcGFnZT8nCgoJCXJldHVybiBnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKHJ1bikKAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/nondet/trivial.0_0.hash b/tests/cases/stable/nondet/trivial.0_0.hash deleted file mode 100644 index 7ee50db85..000000000 --- a/tests/cases/stable/nondet/trivial.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQFMd2ViIHBhZ2U/AAUF diff --git a/tests/cases/stable/nondet/validator/rollback_agree.0.hash b/tests/cases/stable/nondet/validator/rollback_agree.0.hash deleted file mode 100644 index 7b86822f1..000000000 --- a/tests/cases/stable/nondet/validator/rollback_agree.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDEv0AAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYpOgoJCWRlZiBydW4oKToKCQkJcmFpc2UgZ2wudm0uVXNlckVycm9yKCdyb2xsYmFjaycpCgoJCXByaW50KGdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEocnVuKSkKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/nondet/validator/rollback_agree.0_0.hash b/tests/cases/stable/nondet/validator/rollback_agree.0_0.hash deleted file mode 100644 index 42274ec6c..000000000 --- a/tests/cases/stable/nondet/validator/rollback_agree.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQlEcm9sbGJhY2sABQU= diff --git a/tests/cases/stable/nondet/validator/rollback_disagree.0.hash b/tests/cases/stable/nondet/validator/rollback_disagree.0.hash deleted file mode 100644 index 7b86822f1..000000000 --- a/tests/cases/stable/nondet/validator/rollback_disagree.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDEv0AAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYpOgoJCWRlZiBydW4oKToKCQkJcmFpc2UgZ2wudm0uVXNlckVycm9yKCdyb2xsYmFjaycpCgoJCXByaW50KGdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEocnVuKSkKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/nondet/validator/rollback_disagree.0_0.hash b/tests/cases/stable/nondet/validator/rollback_disagree.0_0.hash deleted file mode 100644 index c677e6b07..000000000 --- a/tests/cases/stable/nondet/validator/rollback_disagree.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQl0b3RoZXIgcm9sbGJhY2sABQU= diff --git a/tests/cases/stable/nondet/validator/rollback_imm.0.hash b/tests/cases/stable/nondet/validator/rollback_imm.0.hash deleted file mode 100644 index ad493dbe1..000000000 --- a/tests/cases/stable/nondet/validator/rollback_imm.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDEgEBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYpOgoJCWRlZiBydW4oKToKCQkJZ2wudm0uVXNlckVycm9yLmltbWVkaWF0ZSgncm9sbGJhY2snKQoKCQlwcmludChnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKHJ1bikpCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/nondet/validator/rollback_imm.0_0.hash b/tests/cases/stable/nondet/validator/rollback_imm.0_0.hash deleted file mode 100644 index 42274ec6c..000000000 --- a/tests/cases/stable/nondet/validator/rollback_imm.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQlEcm9sbGJhY2sABQU= diff --git a/tests/cases/stable/nondet/validator/rollback_imm.0_1.hash b/tests/cases/stable/nondet/validator/rollback_imm.0_1.hash deleted file mode 100644 index c677e6b07..000000000 --- a/tests/cases/stable/nondet/validator/rollback_imm.0_1.hash +++ /dev/null @@ -1 +0,0 @@ -LQl0b3RoZXIgcm9sbGJhY2sABQU= diff --git a/tests/cases/stable/nondet/validator/rollback_imm.0_2.hash b/tests/cases/stable/nondet/validator/rollback_imm.0_2.hash deleted file mode 100644 index def506bc7..000000000 --- a/tests/cases/stable/nondet/validator/rollback_imm.0_2.hash +++ /dev/null @@ -1 +0,0 @@ -LQkJAAUF diff --git a/tests/cases/stable/nondet/validator/sync.0.hash b/tests/cases/stable/nondet/validator/sync.0.hash deleted file mode 100644 index 5b6f8290f..000000000 --- a/tests/cases/stable/nondet/validator/sync.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDEgcBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYpOgoJCWRlZiBydW4oKToKCQkJcHJpbnQoJ1NIT1VMRCBOT1QgQkUgUFJJTlRFRCcpCgkJCXJldHVybiAxMAoKCQlwcmludChnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKHJ1bikpCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/nondet/validator/sync.0_0.hash b/tests/cases/stable/nondet/validator/sync.0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/nondet/validator/sync.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/nondet/validator/sync_err.0.hash b/tests/cases/stable/nondet/validator/sync_err.0.hash deleted file mode 100644 index 5b6f8290f..000000000 --- a/tests/cases/stable/nondet/validator/sync_err.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDEgcBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYpOgoJCWRlZiBydW4oKToKCQkJcHJpbnQoJ1NIT1VMRCBOT1QgQkUgUFJJTlRFRCcpCgkJCXJldHVybiAxMAoKCQlwcmludChnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKHJ1bikpCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/nondet/validator/sync_err.0_0.hash b/tests/cases/stable/nondet/validator/sync_err.0_0.hash deleted file mode 100644 index 14442bec8..000000000 --- a/tests/cases/stable/nondet/validator/sync_err.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQk8Tm8gaWRlYQAFBQ== diff --git a/tests/cases/stable/py/balances/balance.0.hash b/tests/cases/stable/py/balances/balance.0.hash deleted file mode 100644 index 920162159..000000000 --- a/tests/cases/stable/py/balances/balance.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDMOICAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwcmludCgnbWFpbiBzZWxmJywgc2VsZi5iYWxhbmNlKQoJCXByaW50KCdtYWluIEF0KHNlbGYpJywgZ2wuY29udHJhY3QuZ2V0X2F0KGdsLm1lc3NhZ2UuY29udHJhY3RfYWRkcmVzcykuYmFsYW5jZSkKCQlwcmludCgnPT09IHRyYW5zZmVyID09PScpCgkJZ2wuY29udHJhY3QuZ2V0X2F0KGdsLm1lc3NhZ2Uuc2VuZGVyX2FkZHJlc3MpLmVtaXRfdHJhbnNmZXIodmFsdWU9NSkKCQlwcmludCgnbWFpbiBzZWxmJywgc2VsZi5iYWxhbmNlKQoJCXByaW50KCdtYWluIEF0KHNlbGYpJywgZ2wuY29udHJhY3QuZ2V0X2F0KGdsLm1lc3NhZ2UuY29udHJhY3RfYWRkcmVzcykuYmFsYW5jZSkKCgkJcHJpbnQoJz09PSBjYWxsIC52aWV3KCkgPT09JykKCQlnbC5jb250cmFjdC5nZXRfYXQoZ2wubWVzc2FnZS5jb250cmFjdF9hZGRyZXNzKS52aWV3KCkubmVzdGVkKCkKCglAZ2wucHVibGljLnZpZXcKCWRlZiBuZXN0ZWQoc2VsZik6CgkJcHJpbnQoJ25lc3RlZCBzZWxmJywgc2VsZi5iYWxhbmNlKQoJCXByaW50KCduZXN0ZWQgQXQoc2VsZiknLCBnbC5jb250cmFjdC5nZXRfYXQoZ2wubWVzc2FnZS5jb250cmFjdF9hZGRyZXNzKS5iYWxhbmNlKQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/balances/balance_eth.0.hash b/tests/cases/stable/py/balances/balance_eth.0.hash deleted file mode 100644 index ced8e3c89..000000000 --- a/tests/cases/stable/py/balances/balance_eth.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDNCEDAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCkBnbC5ldm0uY29udHJhY3RfaW50ZXJmYWNlCmNsYXNzIEV0aENvbnRyYWN0OgoJY2xhc3MgVmlldzoKCQlwYXNzCgoJY2xhc3MgV3JpdGU6CgkJcGFzcwoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwcmludCgnbWFpbiBzZWxmJywgc2VsZi5iYWxhbmNlKQoJCXByaW50KCdtYWluIEF0KHNlbGYpJywgRXRoQ29udHJhY3QoZ2wubWVzc2FnZS5jb250cmFjdF9hZGRyZXNzKS5iYWxhbmNlKQoJCXByaW50KCc9PT0gdHJhbnNmZXIgPT09JykKCgkJRXRoQ29udHJhY3QoZ2wubWVzc2FnZS5zZW5kZXJfYWRkcmVzcykuZW1pdF90cmFuc2Zlcih2YWx1ZT01KQoJCXByaW50KCdtYWluIHNlbGYnLCBzZWxmLmJhbGFuY2UpCgkJcHJpbnQoJ21haW4gQXQoc2VsZiknLCBFdGhDb250cmFjdChnbC5tZXNzYWdlLmNvbnRyYWN0X2FkZHJlc3MpLmJhbGFuY2UpCgoJCXByaW50KCc9PT0gY2FsbCAudmlldygpID09PScpCgkJZ2wuY29udHJhY3QuZ2V0X2F0KGdsLm1lc3NhZ2UuY29udHJhY3RfYWRkcmVzcykudmlldygpLm5lc3RlZCgpCgoJQGdsLnB1YmxpYy52aWV3CglkZWYgbmVzdGVkKHNlbGYpOgoJCXByaW50KCduZXN0ZWQgc2VsZicsIHNlbGYuYmFsYW5jZSkKCQlwcmludCgnbmVzdGVkIEF0KHNlbGYpJywgRXRoQ29udHJhY3QoZ2wubWVzc2FnZS5jb250cmFjdF9hZGRyZXNzKS5iYWxhbmNlKQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/py/balances/sandbox_overspend.0.hash b/tests/cases/stable/py/balances/sandbox_overspend.0.hash deleted file mode 100644 index ce84d0351..000000000 --- a/tests/cases/stable/py/balances/sandbox_overspend.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDRDwEAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJYmFsYW5jZV9iZWZvcmUgPSBzZWxmLmJhbGFuY2UKCQl0YXJnZXQgPSBnbC5tZXNzYWdlLnNlbmRlcl9hZGRyZXNzCgoJCSMgRmlyc3QgdHJhbnNmZXI6IHNwZW5kIDYwIG91dCBvZiAxMDAKCQlnbC5jb250cmFjdC5nZXRfYXQodGFyZ2V0KS5lbWl0X3RyYW5zZmVyKHZhbHVlPTYwKQoJCWJhbGFuY2VfYWZ0ZXJfZmlyc3QgPSBzZWxmLmJhbGFuY2UKCQlwcmludChmJ2JhbGFuY2UgYmVmb3JlPXtiYWxhbmNlX2JlZm9yZX0gYWZ0ZXJfZmlyc3Rfc2VuZD17YmFsYW5jZV9hZnRlcl9maXJzdH0nKQoKCQkjIE5vdyBzcGF3biBhIHNhbmRib3ggd2l0aCB3cml0ZSBvcHMgYWxsb3dlZC4KCQkjIEJVRzogdGhlIHNhbmRib3ggZ2V0cyBhIGZyZXNoIG1lc3NhZ2VzX2RlY3JlbWVudGVkPTAsCgkJIyBzbyBpdCB0aGlua3MgdGhlIGZ1bGwgYmFsYW5jZSBpcyBzdGlsbCBhdmFpbGFibGUuCgkJZGVmIHNhbmRib3hfZm4oKToKCQkJIyBTZWNvbmQgdHJhbnNmZXI6IHNwZW5kIGFub3RoZXIgNjAgaW5zaWRlIHNhbmRib3gKCQkJIyBUaGlzIHNob3VsZCBmYWlsICh0b3RhbCAxMjAgPiAxMDApIGJ1dCB0aGUgc2FuZGJveAoJCQkjIGRvZXNuJ3Qga25vdyBhYm91dCB0aGUgcGFyZW50J3MgNjAgYWxyZWFkeSBzcGVudC4KCQkJZ2wuY29udHJhY3QuZ2V0X2F0KHRhcmdldCkuZW1pdF90cmFuc2Zlcih2YWx1ZT02MCkKCQkJcmV0dXJuIHNlbGYuYmFsYW5jZQoKCQlyZXN1bHQgPSBnbC52bS5zcGF3bl9zYW5kYm94KHNhbmRib3hfZm4sIGFsbG93X3dyaXRlX29wcz1UcnVlKQoJCXByaW50KGYnc2FuZGJveCByZXN1bHQ9e3Jlc3VsdH0nKQoJCXByaW50KGYnYmFsYW5jZSBmaW5hbD17c2VsZi5iYWxhbmNlfScpCgkJIyBJZiB3ZSByZWFjaCBoZXJlIHdpdGggYm90aCB0cmFuc2ZlcnMgYWNjZXB0ZWQsCgkJIyB0b3RhbCBzcGVudCBpcyAxMjAgYnV0IGJhbGFuY2Ugd2FzIG9ubHkgMTAwID0+IG92ZXJzcGVuZCBidWcKBQ== diff --git a/tests/cases/stable/py/balances/sandbox_overspend_2.0.hash b/tests/cases/stable/py/balances/sandbox_overspend_2.0.hash deleted file mode 100644 index edd053d92..000000000 --- a/tests/cases/stable/py/balances/sandbox_overspend_2.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDKGICAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJdGFyZ2V0ID0gZ2wubWVzc2FnZS5zZW5kZXJfYWRkcmVzcwoKCQlwcmludChmJ2JhbGFuY2UgYmVmb3JlPXtzZWxmLmJhbGFuY2V9JykKCgkJZGVmIHNhbmRib3hfZm4oKToKCQkJZ2wuY29udHJhY3QuZ2V0X2F0KHRhcmdldCkuZW1pdF90cmFuc2Zlcih2YWx1ZT02MCkKCQkJcmV0dXJuIHNlbGYuYmFsYW5jZQoKCQlyZXN1bHQgPSBnbC52bS5zcGF3bl9zYW5kYm94KHNhbmRib3hfZm4sIGFsbG93X3dyaXRlX29wcz1UcnVlKQoJCXByaW50KGYnc2FuZGJveCByZXN1bHQ9e3Jlc3VsdH0gYmFsYW5jZSBhZnRlciBzYW5kYm94PXtzZWxmLmJhbGFuY2V9JykKCgkJdHJ5OgoJCQlnbC5jb250cmFjdC5nZXRfYXQodGFyZ2V0KS5lbWl0X3RyYW5zZmVyKHZhbHVlPTYwKQoJCWV4Y2VwdCBFeGNlcHRpb24gYXMgZToKCQkJcHJpbnQoZid0cmFuc2ZlciBmYWlsZWQgd2l0aCBlcnJvcjoge2V9JykKCgkJcHJpbnQoZidiYWxhbmNlIGZpbmFsPXtzZWxmLmJhbGFuY2V9JykKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/py/balances/undefined_all.0.hash b/tests/cases/stable/py/balances/undefined_all.0.hash deleted file mode 100644 index 4a02bbffb..000000000 --- a/tests/cases/stable/py/balances/undefined_all.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDCoYAAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglwYXNzCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/py/balances/undefined_all.0_0.hash b/tests/cases/stable/py/balances/undefined_all.0_0.hash deleted file mode 100644 index 131eae252..000000000 --- a/tests/cases/stable/py/balances/undefined_all.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LRFcZXhpdF9jb2RlIDEABQU= diff --git a/tests/cases/stable/py/balances/undefined_all.0_0_0.hash b/tests/cases/stable/py/balances/undefined_all.0_0_0.hash deleted file mode 100644 index 131eae252..000000000 --- a/tests/cases/stable/py/balances/undefined_all.0_0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LRFcZXhpdF9jb2RlIDEABQU= diff --git a/tests/cases/stable/py/balances/undefined_method.0.hash b/tests/cases/stable/py/balances/undefined_method.0.hash deleted file mode 100644 index 970b748ad..000000000 --- a/tests/cases/stable/py/balances/undefined_method.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDJCsCAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCmltcG9ydCB0eXBpbmcKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgX19oYW5kbGVfdW5kZWZpbmVkX21ldGhvZF9fKAoJCXNlbGYsIG1ldGhvZF9uYW1lOiBzdHIsIGFyZ3M6IGxpc3RbdHlwaW5nLkFueV0sIGt3YXJnczogZGljdFtzdHIsIHR5cGluZy5BbnldCgkpOgoJCXByaW50KAoJCQl7CgkJCQknbWUnOiAnX19oYW5kbGVfdW5kZWZpbmVkX21ldGhvZF9fJywKCQkJCSdtZXRob2RfbmFtZSc6IG1ldGhvZF9uYW1lLAoJCQkJJ2FyZ3MnOiBhcmdzLAoJCQkJJ2t3YXJncyc6IGt3YXJncywKCQkJCSd2YWx1ZSc6IGdsLm1lc3NhZ2UudmFsdWUsCgkJCX0KCQkpCgoJQGdsLnB1YmxpYy53cml0ZS5wYXlhYmxlCglkZWYgX19yZWNlaXZlX18oc2VsZik6CgkJcHJpbnQoeydtZSc6ICdfX3JlY2VpdmVfXycsICd2YWx1ZSc6IGdsLm1lc3NhZ2UudmFsdWV9KQoAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/balances/undefined_method.0_0.hash b/tests/cases/stable/py/balances/undefined_method.0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/balances/undefined_method.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/py/balances/undefined_method.0_0_0.hash b/tests/cases/stable/py/balances/undefined_method.0_0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/balances/undefined_method.0_0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/py/balances/undefined_method_payable.0.hash b/tests/cases/stable/py/balances/undefined_method_payable.0.hash deleted file mode 100644 index 96e6d0fe2..000000000 --- a/tests/cases/stable/py/balances/undefined_method_payable.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDJDMCAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCmltcG9ydCB0eXBpbmcKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlLnBheWFibGUKCWRlZiBfX2hhbmRsZV91bmRlZmluZWRfbWV0aG9kX18oCgkJc2VsZiwgbWV0aG9kX25hbWU6IHN0ciwgYXJnczogbGlzdFt0eXBpbmcuQW55XSwga3dhcmdzOiBkaWN0W3N0ciwgdHlwaW5nLkFueV0KCSk6CgkJcHJpbnQoCgkJCXsKCQkJCSdtZSc6ICdfX2hhbmRsZV91bmRlZmluZWRfbWV0aG9kX18nLAoJCQkJJ21ldGhvZF9uYW1lJzogbWV0aG9kX25hbWUsCgkJCQknYXJncyc6IGFyZ3MsCgkJCQkna3dhcmdzJzoga3dhcmdzLAoJCQkJJ3ZhbHVlJzogZ2wubWVzc2FnZS52YWx1ZSwKCQkJfQoJCSkKCglAZ2wucHVibGljLndyaXRlLnBheWFibGUKCWRlZiBfX3JlY2VpdmVfXyhzZWxmKToKCQlwcmludCh7J21lJzogJ19fcmVjZWl2ZV9fJywgJ3ZhbHVlJzogZ2wubWVzc2FnZS52YWx1ZX0pCgAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/balances/undefined_method_payable.0_0.hash b/tests/cases/stable/py/balances/undefined_method_payable.0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/balances/undefined_method_payable.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/py/balances/undefined_method_payable.0_0_0.hash b/tests/cases/stable/py/balances/undefined_method_payable.0_0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/balances/undefined_method_payable.0_0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/py/balances/undefined_receive.0.hash b/tests/cases/stable/py/balances/undefined_receive.0.hash deleted file mode 100644 index 1cb8d365e..000000000 --- a/tests/cases/stable/py/balances/undefined_receive.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDHsYBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCmltcG9ydCB0eXBpbmcKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlLnBheWFibGUKCWRlZiBfX2hhbmRsZV91bmRlZmluZWRfbWV0aG9kX18oCgkJc2VsZiwgbWV0aG9kX25hbWU6IHN0ciwgYXJnczogbGlzdFt0eXBpbmcuQW55XSwga3dhcmdzOiBkaWN0W3N0ciwgdHlwaW5nLkFueV0KCSk6CgkJcHJpbnQoCgkJCXsKCQkJCSdtZSc6ICdfX2hhbmRsZV91bmRlZmluZWRfbWV0aG9kX18nLAoJCQkJJ21ldGhvZF9uYW1lJzogbWV0aG9kX25hbWUsCgkJCQknYXJncyc6IGFyZ3MsCgkJCQkna3dhcmdzJzoga3dhcmdzLAoJCQkJJ3ZhbHVlJzogZ2wubWVzc2FnZS52YWx1ZSwKCQkJfQoJCSkKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/balances/undefined_receive.0_0.hash b/tests/cases/stable/py/balances/undefined_receive.0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/balances/undefined_receive.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/py/balances/undefined_receive.0_0_0.hash b/tests/cases/stable/py/balances/undefined_receive.0_0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/balances/undefined_receive.0_0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/py/embeddings/simple.0.hash b/tests/cases/stable/py/embeddings/simple.0.hash deleted file mode 100644 index 13b47280e..000000000 --- a/tests/cases/stable/py/embeddings/simple.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDIhACAAAjIHsKIyAgICJTZXEiOiBbCiMgICAgIHsgIkRlcGVuZHMiOiAicHktbGliLWdlbmxheWVyLWVtYmVkZGluZ3M6dGVzdCIgfSwKIyAgICAgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CiMgICBdCiMgfQoKaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKaW1wb3J0IGdlbmxheWVyX2VtYmVkZGluZ3MgYXMgZ2xlCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG1haW4oc2VsZiwgZGV0OiBib29sKToKCQlkZWYgbmRfYmxvY2soKToKCQkJZW1iZWRkaW5nc19nZW5lcmF0b3IgPSBnbGUuU2VudGVuY2VUcmFuc2Zvcm1lcignYWxsLU1pbmlMTS1MNi12MicpCgkJCXJlYWwgPSBlbWJlZGRpbmdzX2dlbmVyYXRvcignd2hhdCBpcyBnZW5sYXllcj8nKQoJCQlwcmludChyZWFsLnN1bSgpKQoKCQlpZiBkZXQ6CgkJCW5kX2Jsb2NrKCkKCQllbHNlOgoJCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKG5kX2Jsb2NrKQoAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/py/embeddings/simple.0_0.hash b/tests/cases/stable/py/embeddings/simple.0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/embeddings/simple.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/py/embeddings/simple_det.0.hash b/tests/cases/stable/py/embeddings/simple_det.0.hash deleted file mode 100644 index 13b47280e..000000000 --- a/tests/cases/stable/py/embeddings/simple_det.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDIhACAAAjIHsKIyAgICJTZXEiOiBbCiMgICAgIHsgIkRlcGVuZHMiOiAicHktbGliLWdlbmxheWVyLWVtYmVkZGluZ3M6dGVzdCIgfSwKIyAgICAgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CiMgICBdCiMgfQoKaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKaW1wb3J0IGdlbmxheWVyX2VtYmVkZGluZ3MgYXMgZ2xlCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG1haW4oc2VsZiwgZGV0OiBib29sKToKCQlkZWYgbmRfYmxvY2soKToKCQkJZW1iZWRkaW5nc19nZW5lcmF0b3IgPSBnbGUuU2VudGVuY2VUcmFuc2Zvcm1lcignYWxsLU1pbmlMTS1MNi12MicpCgkJCXJlYWwgPSBlbWJlZGRpbmdzX2dlbmVyYXRvcignd2hhdCBpcyBnZW5sYXllcj8nKQoJCQlwcmludChyZWFsLnN1bSgpKQoKCQlpZiBkZXQ6CgkJCW5kX2Jsb2NrKCkKCQllbHNlOgoJCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKG5kX2Jsb2NrKQoAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/py/embeddings/simple_det.0_0.hash b/tests/cases/stable/py/embeddings/simple_det.0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/embeddings/simple_det.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/py/embeddings/simple_tokenizer.0.hash b/tests/cases/stable/py/embeddings/simple_tokenizer.0.hash deleted file mode 100644 index 49aa02f77..000000000 --- a/tests/cases/stable/py/embeddings/simple_tokenizer.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDHsABAAAjIHsKIyAgICJTZXEiOiBbCiMgICAgIHsgIkRlcGVuZHMiOiAicHktbGliLXdvcmRfcGllY2VfdG9rZW5pemVyOnRlc3QiIH0sCiMgICAgIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQojICAgXQojIH0KCmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCmltcG9ydCB3b3JkX3BpZWNlX3Rva2VuaXplcgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYsIGRldDogYm9vbCk6CgkJdG9rZW5pemVyID0gd29yZF9waWVjZV90b2tlbml6ZXIuV29yZFBpZWNlVG9rZW5pemVyKCkKCgkJZm9yIHR4dCBpbiBbJyMjJywgJyNoYXNodGFnJywgJ2Vtb2ppIPCfmoDwn5qA8J+agCddOgoJCQlwcmludChmJ3t0eHR9OiB7dG9rZW5pemVyLnRva2VuaXplKHR4dCl9JykKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/embeddings/simple_tokenizer.0_0.hash b/tests/cases/stable/py/embeddings/simple_tokenizer.0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/embeddings/simple_tokenizer.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/py/embeddings/vecdb.0.hash b/tests/cases/stable/py/embeddings/vecdb.0.hash deleted file mode 100644 index 017d30de7..000000000 --- a/tests/cases/stable/py/embeddings/vecdb.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAEUVowIJ6r6p+bC2UceCnPii5HtX+KqB1OxkZieLE2tqmVBnWgAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIaGMO10IwC6z0HwSX6yVN8UD18cm5phpL4avb+rqUUYAAAAAgwIDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAjctRsOtqfiXx000m7/g5FDHmBZ8n1gPja+F3vV+lsPqAAAAAIMGAQAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAM3MzMzMzPQ/AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCnN2bFjS8G1cgPa1WBpyjyG4x+crK62Vpe7OE6Vik+oAAAAAAgwIAAAAAAAAAAAAAAAD/////AAAAAAAAAAAAAAAAAAAAABWjAroAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELAAAAAIMKBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhee6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjArtHW19KeR3j/qGkKz3kHNgU+bllSDToaqVyrtJw9Q7jAAAAAIMCMTIzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowK/3qmf3S8yrjpIVx1Q6ejcB/QQx6foIUwOn3NSI01TlgAAAACDAgAAgD8AAABAAABAQAAAgEAAAKBAAAAAAAAAAAAAAAAAFaMC4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhecAAAAAgyD5AQAAIyB7CiMgICAiU2VxIjogWwojICAgICB7ICJEZXBlbmRzIjogInB5LWxpYi1nZW5sYXllci1lbWJlZGRpbmdzOnRlc3QiIH0sCiMgICAgIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQojICAgXQojIH0KCgppbXBvcnQgbnVtcHkgYXMgbnAKaW1wb3J0IHR5cGluZwppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgppbXBvcnQgZ2VubGF5ZXJfZW1iZWRkaW5ncyBhcyBnbGUKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6Cgl4OiBnbGUuVmVjREJbbnAuZmxvYXQzMiwgdHlwaW5nLkxpdGVyYWxbNV0sIHN0ciwgZ2xlLkV1Y2xpZGVhbkRpc3RhbmNlXQoKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlzZWxmLnguaW5zZXJ0KG5wLmFycmF5KFsxLCAyLCAzLCA0LCA1XSwgZHR5cGU9bnAuZmxvYXQzMiksICcxMjMnKQoJCXByaW50KGxpc3Qoc2VsZi54LmtubihucC5vbmVzKDUsIGR0eXBlPW5wLmZsb2F0MzIpLCAxKSkpCgAAAAU= diff --git a/tests/cases/stable/py/events/post_event.0.hash b/tests/cases/stable/py/events/post_event.0.hash deleted file mode 100644 index 79446bf6b..000000000 --- a/tests/cases/stable/py/events/post_event.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDJlACAAAjIHYwLjEuNQojIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIFRlc3RFdmVudChnbC5jaGFpbi5FdmVudCk6CglkZWYgX19pbml0X18oc2VsZiwgdXNlcl9pZDogaW50LCBhY3Rpb246IHN0ciwgLywgKipibG9iKTogLi4uCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJZGVmIF9faW5pdF9fKHNlbGYpOgoJCXRyeToKCQkJIyBUZXN0IGJhc2ljIGV2ZW50IGVtaXNzaW9uCgkJCVRlc3RFdmVudCg0MiwgJ2NyZWF0ZScsIHRpbWVzdGFtcD0xMjM0NTY3ODkwLCBkYXRhPSd0ZXN0X2RhdGEnKS5lbWl0KCkKCgkJCSMgVGVzdCBldmVudCB3aXRoIGRpZmZlcmVudCBwYXJhbWV0ZXJzCgkJCVRlc3RFdmVudCgxMDAsICd1cGRhdGUnLCBhbW91bnQ9NTAwLCBkZXNjcmlwdGlvbj0nVXBkYXRlZCByZWNvcmQnKS5lbWl0KCkKCgkJCXByaW50KCdFdmVudHMgZW1pdHRlZCBzdWNjZXNzZnVsbHknKQoJCWV4Y2VwdCBFeGNlcHRpb24gYXMgZToKCQkJcHJpbnQoZidFcnJvciBlbWl0dGluZyBldmVudDoge2V9JykKAAAAAAAAAAAAAAAAFSWDArR1HfVl/DVUdk4nkJQ5YMnN/nz1EDMdspiBvxUjtA2sgwLRAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIMCNGNyZWF0ZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7AyYGYWN0aW9u0QIEZGF0YUx0ZXN0X2RhdGEJdGltZXN0YW1wka3A5SQHdXNlcl9pZDRjcmVhdGUlgwK0dR31Zfw1VHZOJ5CUOWDJzf589RAzHbKYgb8VI7QNrIMCoQYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAjR1cGRhdGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6wMmBmFjdGlvbqEGBmFtb3VudKEfC2Rlc2NyaXB0aW9udFVwZGF0ZWQgcmVjb3JkB3VzZXJfaWQ0dXBkYXRl diff --git a/tests/cases/stable/py/intercontract/call_view.0.hash b/tests/cases/stable/py/intercontract/call_view.0.hash deleted file mode 100644 index f296230d4..000000000 --- a/tests/cases/stable/py/intercontract/call_view.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDEhcBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwYXNzCgoJQGdsLnB1YmxpYy52aWV3CglkZWYgZm9vKHNlbGYsIGEsIGIpOgoJCXByaW50KCdjb250cmFjdCB0by5mb28nKQoJCWltcG9ydCBqc29uCgoJCWpzb24ubG9hZHMgPSAxMSAgIyBldmlsIQoJCXJldHVybiBhICsgYgoAAAAAAAU= diff --git a/tests/cases/stable/py/intercontract/call_view.0_0.hash b/tests/cases/stable/py/intercontract/call_view.0_0.hash deleted file mode 100644 index 26d73dafe..000000000 --- a/tests/cases/stable/py/intercontract/call_view.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDFB8BAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwYXNzCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG1haW4oc2VsZiwgYWRkcjogQWRkcmVzcyk6CgkJcHJpbnQoJ2NvbnRyYWN0IGZyb20ubWFpbicpCgkJcHJpbnQoZ2wuY29udHJhY3QuZ2V0X2F0KGFkZHIpLnZpZXcoKS5mb28oMSwgMikpCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/intercontract/call_view.0_0_0.hash b/tests/cases/stable/py/intercontract/call_view.0_0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/intercontract/call_view.0_0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/py/intercontract/call_view_iface.0.hash b/tests/cases/stable/py/intercontract/call_view_iface.0.hash deleted file mode 100644 index f296230d4..000000000 --- a/tests/cases/stable/py/intercontract/call_view_iface.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDEhcBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwYXNzCgoJQGdsLnB1YmxpYy52aWV3CglkZWYgZm9vKHNlbGYsIGEsIGIpOgoJCXByaW50KCdjb250cmFjdCB0by5mb28nKQoJCWltcG9ydCBqc29uCgoJCWpzb24ubG9hZHMgPSAxMSAgIyBldmlsIQoJCXJldHVybiBhICsgYgoAAAAAAAU= diff --git a/tests/cases/stable/py/intercontract/call_view_iface.0_0.hash b/tests/cases/stable/py/intercontract/call_view_iface.0_0.hash deleted file mode 100644 index 3341507a4..000000000 --- a/tests/cases/stable/py/intercontract/call_view_iface.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDGF0BAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCkBnbC5jb250cmFjdC5pbnRlcmZhY2UKY2xhc3MgVG9JZmFjZToKCWNsYXNzIFZpZXc6CgkJZGVmIGZvbyhzZWxmLCBhLCBiKTogLi4uCgoJY2xhc3MgV3JpdGU6CgkJcGFzcwoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYsIGFkZHI6IEFkZHJlc3MpOgoJCXByaW50KCdjb250cmFjdCBmcm9tLm1haW4nKQoJCXByaW50KFRvSWZhY2UoYWRkcikudmlldygpLmZvbygxLCAyKSkKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/intercontract/call_view_iface.0_0_0.hash b/tests/cases/stable/py/intercontract/call_view_iface.0_0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/intercontract/call_view_iface.0_0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/py/intercontract/deploy.0.hash b/tests/cases/stable/py/intercontract/deploy.0.hash deleted file mode 100644 index bc7a431dc..000000000 --- a/tests/cases/stable/py/intercontract/deploy.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDDtcAAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlnbC5jb250cmFjdC5kZXBsb3koY29kZT0nbm90IHJlYWxseSBhIGNvbnRyYWN0Jy5lbmNvZGUoJ3V0Zi04JykpCgAAAAAABQ== diff --git a/tests/cases/stable/py/intercontract/deploy_salt.0.hash b/tests/cases/stable/py/intercontract/deploy_salt.0.hash deleted file mode 100644 index 53f462d44..000000000 --- a/tests/cases/stable/py/intercontract/deploy_salt.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDEPgAAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlyZXMgPSBnbC5jb250cmFjdC5kZXBsb3koY29kZT0nbm90IHJlYWxseSBhIGNvbnRyYWN0Jy5lbmNvZGUoJ3V0Zi04JyksIHNhbHRfbm9uY2U9MSkKCQlwcmludChyZXMpCgAAAAAF diff --git a/tests/cases/stable/py/intercontract/eth_call_view.0.hash b/tests/cases/stable/py/intercontract/eth_call_view.0.hash deleted file mode 100644 index c0593583d..000000000 --- a/tests/cases/stable/py/intercontract/eth_call_view.0.hash +++ /dev/null @@ -1 +0,0 @@ -LRF0aG9zdCBmb3JiaWRkZW4AFRWjAroAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELAAAAAIMKBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhee6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAuGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnAAAAAIMagAEAACMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCgoKQGdsLmV2bS5jb250cmFjdF9pbnRlcmZhY2UKY2xhc3MgR2hvc3Q6CgljbGFzcyBWaWV3OgoJCWRlZiB0ZXN0KHNlbGYsIHg6IHUyNTYsIC8pIC0+IHUyNTY6IC4uLgoKCWNsYXNzIFdyaXRlOgoJCXBhc3MKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJdHJ5OgoJCQlHaG9zdChBZGRyZXNzKGInXHgzMCcgKiAyMCkpLnZpZXcoKS50ZXN0KDEwKQoJCWV4Y2VwdCBCYXNlRXhjZXB0aW9uIGFzIGU6CgkJCXByaW50KGYnZXhwZWN0ZWQgZXJyb3I6IHtlfScpCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/py/intercontract/send_message.0.hash b/tests/cases/stable/py/intercontract/send_message.0.hash deleted file mode 100644 index 75d332400..000000000 --- a/tests/cases/stable/py/intercontract/send_message.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDDtQAAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlnbC5jb250cmFjdC5nZXRfYXQoZ2wuQWRkcmVzcyhiJ1x4MzAnICogMjApKS5lbWl0KCkuZm9vKDEsIDIpCgAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/intercontract/send_message_eth.0.hash b/tests/cases/stable/py/intercontract/send_message_eth.0.hash deleted file mode 100644 index 8264b037c..000000000 --- a/tests/cases/stable/py/intercontract/send_message_eth.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDFlgBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCkBnbC5ldm0uY29udHJhY3RfaW50ZXJmYWNlCmNsYXNzIEdob3N0OgoJY2xhc3MgVmlldzoKCQlwYXNzCgoJY2xhc3MgV3JpdGU6CgkJZGVmIHRlc3Qoc2VsZiwgeDogdTI1NiwgLykgLT4gTm9uZTogLi4uCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJZGVmIF9faW5pdF9fKHNlbGYpOgoJCXByaW50KHNlbGYuYmFsYW5jZSkKCQlHaG9zdChBZGRyZXNzKGInXHgzMCcgKiAyMCkpLmVtaXQodmFsdWU9MzApLnRlc3QoMTApCgAAAAAF diff --git a/tests/cases/stable/py/intercontract/send_message_on.0.hash b/tests/cases/stable/py/intercontract/send_message_on.0.hash deleted file mode 100644 index 7d93db8f9..000000000 --- a/tests/cases/stable/py/intercontract/send_message_on.0.hash +++ /dev/null @@ -1 +0,0 @@ -LRFcZXhpdF9jb2RlIDEAFRWjAroAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELAAAAAIMKBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhee6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAuGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnAAAAAIMUHwEAACMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG1haW4oc2VsZiwgb246IHN0cik6CgkJdHJ5OgoJCQlnbC5jb250cmFjdC5nZXRfYXQoZ2wuQWRkcmVzcyhiJ1x4MzAnICogMjApKS5lbWl0KG9uPW9uKS5mb28oMSwgMikKCQlleGNlcHQgU3lzdGVtRXJyb3IgYXMgZToKCQkJcHJpbnQoZSkKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/py/intercontract/send_message_on.0_0.hash b/tests/cases/stable/py/intercontract/send_message_on.0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/intercontract/send_message_on.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/py/intercontract/send_message_on.0_0_0.hash b/tests/cases/stable/py/intercontract/send_message_on.0_0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/intercontract/send_message_on.0_0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/py/other/meth/method_init.0.hash b/tests/cases/stable/py/other/meth/method_init.0.hash deleted file mode 100644 index c843f0091..000000000 --- a/tests/cases/stable/py/other/meth/method_init.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDKHwCAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwcmludCgnaW5pdCcpCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIHB1YihzZWxmKToKCQlldmFsKCJwcmludCgnaW5pdCBmcm9tIHB1YiEnKSIpCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIHJiYWNrKHNlbGYpOgoJCWdsLnZtLlVzZXJFcnJvci5pbW1lZGlhdGUoIm5haCwgSSB3b24ndCBleGVjdXRlIikKCglkZWYgcHJpdihzZWxmKToKCQlldmFsKCJwcmludCgnaW5pdCBmcm9tIHByaXYhJykiKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiByZXRuKHNlbGYpOgoJCXJldHVybiB7J3gnOiAxMH0KCglAZ2wucHVibGljLnZpZXcKCWRlZiByZXRuX3ZpZXcoc2VsZik6CgkJcmV0dXJuIHsneCc6IDEwfQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBkZXRfdmlvbChzZWxmKToKCQlnbC5ub25kZXQud2ViLnJlbmRlcigKCQkJJ2h0dHBzOi8vdGVzdC1zZXJ2ZXIuZ2VubGF5ZXIuY29tL3N0YXRpYy9nZW52bS9oZWxsby5odG1sJywKCQkJbW9kZT0ndGV4dCcsCgkJKQoF diff --git a/tests/cases/stable/py/other/meth/method_init_wrong_name.0.hash b/tests/cases/stable/py/other/meth/method_init_wrong_name.0.hash deleted file mode 100644 index c843f0091..000000000 --- a/tests/cases/stable/py/other/meth/method_init_wrong_name.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDKHwCAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwcmludCgnaW5pdCcpCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIHB1YihzZWxmKToKCQlldmFsKCJwcmludCgnaW5pdCBmcm9tIHB1YiEnKSIpCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIHJiYWNrKHNlbGYpOgoJCWdsLnZtLlVzZXJFcnJvci5pbW1lZGlhdGUoIm5haCwgSSB3b24ndCBleGVjdXRlIikKCglkZWYgcHJpdihzZWxmKToKCQlldmFsKCJwcmludCgnaW5pdCBmcm9tIHByaXYhJykiKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiByZXRuKHNlbGYpOgoJCXJldHVybiB7J3gnOiAxMH0KCglAZ2wucHVibGljLnZpZXcKCWRlZiByZXRuX3ZpZXcoc2VsZik6CgkJcmV0dXJuIHsneCc6IDEwfQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBkZXRfdmlvbChzZWxmKToKCQlnbC5ub25kZXQud2ViLnJlbmRlcigKCQkJJ2h0dHBzOi8vdGVzdC1zZXJ2ZXIuZ2VubGF5ZXIuY29tL3N0YXRpYy9nZW52bS9oZWxsby5odG1sJywKCQkJbW9kZT0ndGV4dCcsCgkJKQoF diff --git a/tests/cases/stable/py/other/meth/method_public.0.hash b/tests/cases/stable/py/other/meth/method_public.0.hash deleted file mode 100644 index c843f0091..000000000 --- a/tests/cases/stable/py/other/meth/method_public.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDKHwCAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwcmludCgnaW5pdCcpCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIHB1YihzZWxmKToKCQlldmFsKCJwcmludCgnaW5pdCBmcm9tIHB1YiEnKSIpCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIHJiYWNrKHNlbGYpOgoJCWdsLnZtLlVzZXJFcnJvci5pbW1lZGlhdGUoIm5haCwgSSB3b24ndCBleGVjdXRlIikKCglkZWYgcHJpdihzZWxmKToKCQlldmFsKCJwcmludCgnaW5pdCBmcm9tIHByaXYhJykiKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiByZXRuKHNlbGYpOgoJCXJldHVybiB7J3gnOiAxMH0KCglAZ2wucHVibGljLnZpZXcKCWRlZiByZXRuX3ZpZXcoc2VsZik6CgkJcmV0dXJuIHsneCc6IDEwfQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBkZXRfdmlvbChzZWxmKToKCQlnbC5ub25kZXQud2ViLnJlbmRlcigKCQkJJ2h0dHBzOi8vdGVzdC1zZXJ2ZXIuZ2VubGF5ZXIuY29tL3N0YXRpYy9nZW52bS9oZWxsby5odG1sJywKCQkJbW9kZT0ndGV4dCcsCgkJKQoF diff --git a/tests/cases/stable/py/other/meth/method_public.0_0.hash b/tests/cases/stable/py/other/meth/method_public.0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/other/meth/method_public.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/py/other/meth/method_retn.0.hash b/tests/cases/stable/py/other/meth/method_retn.0.hash deleted file mode 100644 index c843f0091..000000000 --- a/tests/cases/stable/py/other/meth/method_retn.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDKHwCAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwcmludCgnaW5pdCcpCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIHB1YihzZWxmKToKCQlldmFsKCJwcmludCgnaW5pdCBmcm9tIHB1YiEnKSIpCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIHJiYWNrKHNlbGYpOgoJCWdsLnZtLlVzZXJFcnJvci5pbW1lZGlhdGUoIm5haCwgSSB3b24ndCBleGVjdXRlIikKCglkZWYgcHJpdihzZWxmKToKCQlldmFsKCJwcmludCgnaW5pdCBmcm9tIHByaXYhJykiKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiByZXRuKHNlbGYpOgoJCXJldHVybiB7J3gnOiAxMH0KCglAZ2wucHVibGljLnZpZXcKCWRlZiByZXRuX3ZpZXcoc2VsZik6CgkJcmV0dXJuIHsneCc6IDEwfQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBkZXRfdmlvbChzZWxmKToKCQlnbC5ub25kZXQud2ViLnJlbmRlcigKCQkJJ2h0dHBzOi8vdGVzdC1zZXJ2ZXIuZ2VubGF5ZXIuY29tL3N0YXRpYy9nZW52bS9oZWxsby5odG1sJywKCQkJbW9kZT0ndGV4dCcsCgkJKQoF diff --git a/tests/cases/stable/py/other/meth/method_retn.0_0.hash b/tests/cases/stable/py/other/meth/method_retn.0_0.hash deleted file mode 100644 index ac9183e6f..000000000 --- a/tests/cases/stable/py/other/meth/method_retn.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEOAXhRAAUF diff --git a/tests/cases/stable/py/other/meth/method_retn_view.0.hash b/tests/cases/stable/py/other/meth/method_retn_view.0.hash deleted file mode 100644 index c843f0091..000000000 --- a/tests/cases/stable/py/other/meth/method_retn_view.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDKHwCAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwcmludCgnaW5pdCcpCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIHB1YihzZWxmKToKCQlldmFsKCJwcmludCgnaW5pdCBmcm9tIHB1YiEnKSIpCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIHJiYWNrKHNlbGYpOgoJCWdsLnZtLlVzZXJFcnJvci5pbW1lZGlhdGUoIm5haCwgSSB3b24ndCBleGVjdXRlIikKCglkZWYgcHJpdihzZWxmKToKCQlldmFsKCJwcmludCgnaW5pdCBmcm9tIHByaXYhJykiKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiByZXRuKHNlbGYpOgoJCXJldHVybiB7J3gnOiAxMH0KCglAZ2wucHVibGljLnZpZXcKCWRlZiByZXRuX3ZpZXcoc2VsZik6CgkJcmV0dXJuIHsneCc6IDEwfQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBkZXRfdmlvbChzZWxmKToKCQlnbC5ub25kZXQud2ViLnJlbmRlcigKCQkJJ2h0dHBzOi8vdGVzdC1zZXJ2ZXIuZ2VubGF5ZXIuY29tL3N0YXRpYy9nZW52bS9oZWxsby5odG1sJywKCQkJbW9kZT0ndGV4dCcsCgkJKQoF diff --git a/tests/cases/stable/py/other/meth/method_retn_view.0_0.hash b/tests/cases/stable/py/other/meth/method_retn_view.0_0.hash deleted file mode 100644 index ac9183e6f..000000000 --- a/tests/cases/stable/py/other/meth/method_retn_view.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEOAXhRAAUF diff --git a/tests/cases/stable/py/other/meth/method_rollback.0.hash b/tests/cases/stable/py/other/meth/method_rollback.0.hash deleted file mode 100644 index c843f0091..000000000 --- a/tests/cases/stable/py/other/meth/method_rollback.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDKHwCAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwcmludCgnaW5pdCcpCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIHB1YihzZWxmKToKCQlldmFsKCJwcmludCgnaW5pdCBmcm9tIHB1YiEnKSIpCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIHJiYWNrKHNlbGYpOgoJCWdsLnZtLlVzZXJFcnJvci5pbW1lZGlhdGUoIm5haCwgSSB3b24ndCBleGVjdXRlIikKCglkZWYgcHJpdihzZWxmKToKCQlldmFsKCJwcmludCgnaW5pdCBmcm9tIHByaXYhJykiKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiByZXRuKHNlbGYpOgoJCXJldHVybiB7J3gnOiAxMH0KCglAZ2wucHVibGljLnZpZXcKCWRlZiByZXRuX3ZpZXcoc2VsZik6CgkJcmV0dXJuIHsneCc6IDEwfQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBkZXRfdmlvbChzZWxmKToKCQlnbC5ub25kZXQud2ViLnJlbmRlcigKCQkJJ2h0dHBzOi8vdGVzdC1zZXJ2ZXIuZ2VubGF5ZXIuY29tL3N0YXRpYy9nZW52bS9oZWxsby5odG1sJywKCQkJbW9kZT0ndGV4dCcsCgkJKQoF diff --git a/tests/cases/stable/py/other/meth/method_rollback.0_0.hash b/tests/cases/stable/py/other/meth/method_rollback.0_0.hash deleted file mode 100644 index ed0398513..000000000 --- a/tests/cases/stable/py/other/meth/method_rollback.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQmkAW5haCwgSSB3b24ndCBleGVjdXRlAAUF diff --git a/tests/cases/stable/py/other/ret/returns.0.hash b/tests/cases/stable/py/other/ret/returns.0.hash deleted file mode 100644 index a87d01180..000000000 --- a/tests/cases/stable/py/other/ret/returns.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDGpIBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYsIGlkeDogaW50KToKCQlyZXQgPSBbCgkJCUFkZHJlc3MoYidceDAxJyAqIDIwKSwKCQkJJ2FiYycsCgkJCTEyMywKCQkJYid4eXonLAoJCQlUcnVlLAoJCQlOb25lLAoJCQlGYWxzZSwKCQkJW0FkZHJlc3MoYidceDAyJyAqIDIwKSwgQWRkcmVzcyhiJ1x4MDMnICogMjApXSwKCQkJeydhJzogMSwgJ2InOiBbMSwgMiwgM119LAoJCV0KCQlwcmludChmJ3tpZHh9IFswLi4ue2xlbihyZXQpfSknKQoJCXJldHVybiByZXRbaWR4XQoAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/other/ret/returns.0_0.hash b/tests/cases/stable/py/other/ret/returns.0_0.hash deleted file mode 100644 index 373e64783..000000000 --- a/tests/cases/stable/py/other/ret/returns.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEYAQEBAQEBAQEBAQEBAQEBAQEBAQEABQU= diff --git a/tests/cases/stable/py/other/ret/returns.1.hash b/tests/cases/stable/py/other/ret/returns.1.hash deleted file mode 100644 index a87d01180..000000000 --- a/tests/cases/stable/py/other/ret/returns.1.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDGpIBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYsIGlkeDogaW50KToKCQlyZXQgPSBbCgkJCUFkZHJlc3MoYidceDAxJyAqIDIwKSwKCQkJJ2FiYycsCgkJCTEyMywKCQkJYid4eXonLAoJCQlUcnVlLAoJCQlOb25lLAoJCQlGYWxzZSwKCQkJW0FkZHJlc3MoYidceDAyJyAqIDIwKSwgQWRkcmVzcyhiJ1x4MDMnICogMjApXSwKCQkJeydhJzogMSwgJ2InOiBbMSwgMiwgM119LAoJCV0KCQlwcmludChmJ3tpZHh9IFswLi4ue2xlbihyZXQpfSknKQoJCXJldHVybiByZXRbaWR4XQoAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/other/ret/returns.1_0.hash b/tests/cases/stable/py/other/ret/returns.1_0.hash deleted file mode 100644 index fcc9cff46..000000000 --- a/tests/cases/stable/py/other/ret/returns.1_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEcYWJjAAUF diff --git a/tests/cases/stable/py/other/ret/returns.2.hash b/tests/cases/stable/py/other/ret/returns.2.hash deleted file mode 100644 index a87d01180..000000000 --- a/tests/cases/stable/py/other/ret/returns.2.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDGpIBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYsIGlkeDogaW50KToKCQlyZXQgPSBbCgkJCUFkZHJlc3MoYidceDAxJyAqIDIwKSwKCQkJJ2FiYycsCgkJCTEyMywKCQkJYid4eXonLAoJCQlUcnVlLAoJCQlOb25lLAoJCQlGYWxzZSwKCQkJW0FkZHJlc3MoYidceDAyJyAqIDIwKSwgQWRkcmVzcyhiJ1x4MDMnICogMjApXSwKCQkJeydhJzogMSwgJ2InOiBbMSwgMiwgM119LAoJCV0KCQlwcmludChmJ3tpZHh9IFswLi4ue2xlbihyZXQpfSknKQoJCXJldHVybiByZXRbaWR4XQoAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/other/ret/returns.2_0.hash b/tests/cases/stable/py/other/ret/returns.2_0.hash deleted file mode 100644 index ae3321495..000000000 --- a/tests/cases/stable/py/other/ret/returns.2_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQHZBwAFBQ== diff --git a/tests/cases/stable/py/other/ret/returns.3.hash b/tests/cases/stable/py/other/ret/returns.3.hash deleted file mode 100644 index a87d01180..000000000 --- a/tests/cases/stable/py/other/ret/returns.3.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDGpIBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYsIGlkeDogaW50KToKCQlyZXQgPSBbCgkJCUFkZHJlc3MoYidceDAxJyAqIDIwKSwKCQkJJ2FiYycsCgkJCTEyMywKCQkJYid4eXonLAoJCQlUcnVlLAoJCQlOb25lLAoJCQlGYWxzZSwKCQkJW0FkZHJlc3MoYidceDAyJyAqIDIwKSwgQWRkcmVzcyhiJ1x4MDMnICogMjApXSwKCQkJeydhJzogMSwgJ2InOiBbMSwgMiwgM119LAoJCV0KCQlwcmludChmJ3tpZHh9IFswLi4ue2xlbihyZXQpfSknKQoJCXJldHVybiByZXRbaWR4XQoAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/other/ret/returns.3_0.hash b/tests/cases/stable/py/other/ret/returns.3_0.hash deleted file mode 100644 index 1c55f7e94..000000000 --- a/tests/cases/stable/py/other/ret/returns.3_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEbeHl6AAUF diff --git a/tests/cases/stable/py/other/ret/returns.4.hash b/tests/cases/stable/py/other/ret/returns.4.hash deleted file mode 100644 index a87d01180..000000000 --- a/tests/cases/stable/py/other/ret/returns.4.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDGpIBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYsIGlkeDogaW50KToKCQlyZXQgPSBbCgkJCUFkZHJlc3MoYidceDAxJyAqIDIwKSwKCQkJJ2FiYycsCgkJCTEyMywKCQkJYid4eXonLAoJCQlUcnVlLAoJCQlOb25lLAoJCQlGYWxzZSwKCQkJW0FkZHJlc3MoYidceDAyJyAqIDIwKSwgQWRkcmVzcyhiJ1x4MDMnICogMjApXSwKCQkJeydhJzogMSwgJ2InOiBbMSwgMiwgM119LAoJCV0KCQlwcmludChmJ3tpZHh9IFswLi4ue2xlbihyZXQpfSknKQoJCXJldHVybiByZXRbaWR4XQoAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/other/ret/returns.4_0.hash b/tests/cases/stable/py/other/ret/returns.4_0.hash deleted file mode 100644 index 911179dae..000000000 --- a/tests/cases/stable/py/other/ret/returns.4_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEQAAUF diff --git a/tests/cases/stable/py/other/ret/returns.5.hash b/tests/cases/stable/py/other/ret/returns.5.hash deleted file mode 100644 index a87d01180..000000000 --- a/tests/cases/stable/py/other/ret/returns.5.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDGpIBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYsIGlkeDogaW50KToKCQlyZXQgPSBbCgkJCUFkZHJlc3MoYidceDAxJyAqIDIwKSwKCQkJJ2FiYycsCgkJCTEyMywKCQkJYid4eXonLAoJCQlUcnVlLAoJCQlOb25lLAoJCQlGYWxzZSwKCQkJW0FkZHJlc3MoYidceDAyJyAqIDIwKSwgQWRkcmVzcyhiJ1x4MDMnICogMjApXSwKCQkJeydhJzogMSwgJ2InOiBbMSwgMiwgM119LAoJCV0KCQlwcmludChmJ3tpZHh9IFswLi4ue2xlbihyZXQpfSknKQoJCXJldHVybiByZXRbaWR4XQoAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/other/ret/returns.5_0.hash b/tests/cases/stable/py/other/ret/returns.5_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/other/ret/returns.5_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/py/other/ret/returns.6.hash b/tests/cases/stable/py/other/ret/returns.6.hash deleted file mode 100644 index a87d01180..000000000 --- a/tests/cases/stable/py/other/ret/returns.6.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDGpIBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYsIGlkeDogaW50KToKCQlyZXQgPSBbCgkJCUFkZHJlc3MoYidceDAxJyAqIDIwKSwKCQkJJ2FiYycsCgkJCTEyMywKCQkJYid4eXonLAoJCQlUcnVlLAoJCQlOb25lLAoJCQlGYWxzZSwKCQkJW0FkZHJlc3MoYidceDAyJyAqIDIwKSwgQWRkcmVzcyhiJ1x4MDMnICogMjApXSwKCQkJeydhJzogMSwgJ2InOiBbMSwgMiwgM119LAoJCV0KCQlwcmludChmJ3tpZHh9IFswLi4ue2xlbihyZXQpfSknKQoJCXJldHVybiByZXRbaWR4XQoAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/other/ret/returns.6_0.hash b/tests/cases/stable/py/other/ret/returns.6_0.hash deleted file mode 100644 index f9aa455c2..000000000 --- a/tests/cases/stable/py/other/ret/returns.6_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEIAAUF diff --git a/tests/cases/stable/py/other/ret/returns.7.hash b/tests/cases/stable/py/other/ret/returns.7.hash deleted file mode 100644 index a87d01180..000000000 --- a/tests/cases/stable/py/other/ret/returns.7.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDGpIBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYsIGlkeDogaW50KToKCQlyZXQgPSBbCgkJCUFkZHJlc3MoYidceDAxJyAqIDIwKSwKCQkJJ2FiYycsCgkJCTEyMywKCQkJYid4eXonLAoJCQlUcnVlLAoJCQlOb25lLAoJCQlGYWxzZSwKCQkJW0FkZHJlc3MoYidceDAyJyAqIDIwKSwgQWRkcmVzcyhiJ1x4MDMnICogMjApXSwKCQkJeydhJzogMSwgJ2InOiBbMSwgMiwgM119LAoJCV0KCQlwcmludChmJ3tpZHh9IFswLi4ue2xlbihyZXQpfSknKQoJCXJldHVybiByZXRbaWR4XQoAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/other/ret/returns.7_0.hash b/tests/cases/stable/py/other/ret/returns.7_0.hash deleted file mode 100644 index a870ecc23..000000000 --- a/tests/cases/stable/py/other/ret/returns.7_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEVGAICAgICAgICAgICAgICAgICAgICGAMDAwMDAwMDAwMDAwMDAwMDAwMDAAUF diff --git a/tests/cases/stable/py/other/ret/returns.8.hash b/tests/cases/stable/py/other/ret/returns.8.hash deleted file mode 100644 index a87d01180..000000000 --- a/tests/cases/stable/py/other/ret/returns.8.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDGpIBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYsIGlkeDogaW50KToKCQlyZXQgPSBbCgkJCUFkZHJlc3MoYidceDAxJyAqIDIwKSwKCQkJJ2FiYycsCgkJCTEyMywKCQkJYid4eXonLAoJCQlUcnVlLAoJCQlOb25lLAoJCQlGYWxzZSwKCQkJW0FkZHJlc3MoYidceDAyJyAqIDIwKSwgQWRkcmVzcyhiJ1x4MDMnICogMjApXSwKCQkJeydhJzogMSwgJ2InOiBbMSwgMiwgM119LAoJCV0KCQlwcmludChmJ3tpZHh9IFswLi4ue2xlbihyZXQpfSknKQoJCXJldHVybiByZXRbaWR4XQoAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/other/ret/returns.8_0.hash b/tests/cases/stable/py/other/ret/returns.8_0.hash deleted file mode 100644 index c2ca05777..000000000 --- a/tests/cases/stable/py/other/ret/returns.8_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEWAWEJAWIdCREZAAUF diff --git a/tests/cases/stable/py/other/ret/returns.9.hash b/tests/cases/stable/py/other/ret/returns.9.hash deleted file mode 100644 index a87d01180..000000000 --- a/tests/cases/stable/py/other/ret/returns.9.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDGpIBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYsIGlkeDogaW50KToKCQlyZXQgPSBbCgkJCUFkZHJlc3MoYidceDAxJyAqIDIwKSwKCQkJJ2FiYycsCgkJCTEyMywKCQkJYid4eXonLAoJCQlUcnVlLAoJCQlOb25lLAoJCQlGYWxzZSwKCQkJW0FkZHJlc3MoYidceDAyJyAqIDIwKSwgQWRkcmVzcyhiJ1x4MDMnICogMjApXSwKCQkJeydhJzogMSwgJ2InOiBbMSwgMiwgM119LAoJCV0KCQlwcmludChmJ3tpZHh9IFswLi4ue2xlbihyZXQpfSknKQoJCXJldHVybiByZXRbaWR4XQoAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/other/ret/returns.9_0.hash b/tests/cases/stable/py/other/ret/returns.9_0.hash deleted file mode 100644 index 131eae252..000000000 --- a/tests/cases/stable/py/other/ret/returns.9_0.hash +++ /dev/null @@ -1 +0,0 @@ -LRFcZXhpdF9jb2RlIDEABQU= diff --git a/tests/cases/stable/py/pitfalls/multi_contract.0.hash b/tests/cases/stable/py/pitfalls/multi_contract.0.hash deleted file mode 100644 index 801467ad5..000000000 --- a/tests/cases/stable/py/pitfalls/multi_contract.0.hash +++ /dev/null @@ -1 +0,0 @@ -LRFcZXhpdF9jb2RlIDEADRWjAuGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnAAAAAIMSAQEAACMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCgoKY2xhc3MgQ29udHJhY3QxKGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwcmludCgnaGVsbG8gd29ybGQnKQoKCmNsYXNzIENvbnRyYWN0MihnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcHJpbnQoJ2hlbGxvIHdvcmxkJykKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/pitfalls/pub_ctor.0.hash b/tests/cases/stable/py/pitfalls/pub_ctor.0.hash deleted file mode 100644 index 18731dd97..000000000 --- a/tests/cases/stable/py/pitfalls/pub_ctor.0.hash +++ /dev/null @@ -1 +0,0 @@ -LRFcZXhpdF9jb2RlIDEAFRWjAroAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELAAAAAIMKBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhee6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAuGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnAAAAAIMOvQAAACMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIF9faW5pdF9fKHNlbGYpOgoJCXByaW50KCdoZWxsbyB3b3JsZCcpCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/py/pitfalls/store_proxy.0.hash b/tests/cases/stable/py/pitfalls/store_proxy.0.hash deleted file mode 100644 index 3e02af91a..000000000 --- a/tests/cases/stable/py/pitfalls/store_proxy.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAC0VowI3LUbDran4l8dNNJu/4ORQx5gWfJ9YD42vhd71fpbD6gAAAACDAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF57oAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCv96pn90vMq46SFcdUOno3Af0EMen6CFMDp9zUiNNU5YAAAAAgwISAAAA4m1FZwAAAAAyeQYAAAAAAAAAAAAAAAAAAAAAABWjAuGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnAAAAAIMkNQIAACMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCmZyb20gZ2VubGF5ZXIuc3RvcmFnZSBpbXBvcnQgYWxsb3cKCmZyb20gZGF0YWNsYXNzZXMgaW1wb3J0IGRhdGFjbGFzcwppbXBvcnQgZGF0ZXRpbWUKCgpAYWxsb3cKQGRhdGFjbGFzcwpjbGFzcyBVc2VyOgoJbmFtZTogc3RyCgliaXJ0aGRheTogZGF0ZXRpbWUuZGF0ZXRpbWUKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6Cgl1c2VyczogZ2wuRHluQXJyYXlbVXNlcl0KCglkZWYgX19pbml0X18oc2VsZik6CgkJc2VsZi51c2Vycy5hcHBlbmQoVXNlcignQWRhJywgZGF0ZXRpbWUuZGF0ZXRpbWUubm93KCkpKQoJCXVzZXIgPSBzZWxmLnVzZXJzWy0xXQoJCXNlbGYudXNlcnNbLTFdID0gVXNlcignRGVmaW5pdGVseSBub3QgQWRhJywgZGF0ZXRpbWUuZGF0ZXRpbWUubm93KCkpCgkJcHJpbnQodXNlci5uYW1lKQoJCWFzc2VydCB1c2VyLm5hbWUgPT0gJ0RlZmluaXRlbHkgbm90IEFkYScgICMgdGhpcyBpcyB0cnVlIQoAAAAAAAAAFaMC6nD8K3gCb4SpCyrog3ZrMG+V3kHCLbC+BVt0XWuV9B8AAAAAgwJEZWZpbml0ZWx5IG5vdCBBZGEAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/rollbacks/call_view.0.hash b/tests/cases/stable/py/rollbacks/call_view.0.hash deleted file mode 100644 index 25ec2f05e..000000000 --- a/tests/cases/stable/py/rollbacks/call_view.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDEhwBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwYXNzCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGZvbyhzZWxmLCBhLCBiKToKCQlwcmludCgnY29udHJhY3QgdG8uZm9vJykKCQlnbC52bS5Vc2VyRXJyb3IuaW1tZWRpYXRlKGYibmFoLCBJIHdvbid0IGV4ZWN1dGUge2EgKyBifSIpCgU= diff --git a/tests/cases/stable/py/rollbacks/call_view.0_0.hash b/tests/cases/stable/py/rollbacks/call_view.0_0.hash deleted file mode 100644 index cc56b3ea8..000000000 --- a/tests/cases/stable/py/rollbacks/call_view.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDGogBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwYXNzCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG1haW4oc2VsZiwgYWRkcjogQWRkcmVzcyk6CgkJcHJpbnQoJ2NvbnRyYWN0IGZyb20ubWFpbicpCgkJdHJ5OgoJCQlyZXMgPSBnbC5jb250cmFjdC5nZXRfYXQoYWRkcikudmlldygpLmZvbygxLCAyKS5nZXQoKQoJCWV4Y2VwdCBnbC52bS5Vc2VyRXJyb3IgYXMgcjoKCQkJcHJpbnQoJ2hhbmRsZWQnLCByLmRhdGEpCgkJZWxzZToKCQkJcHJpbnQocmVzKQoJCQlleGl0KDEpCgAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/rollbacks/call_view.0_0_0.hash b/tests/cases/stable/py/rollbacks/call_view.0_0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/rollbacks/call_view.0_0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/py/rollbacks/calldata_rollback.0.hash b/tests/cases/stable/py/rollbacks/calldata_rollback.0.hash deleted file mode 100644 index b8442af4a..000000000 --- a/tests/cases/stable/py/rollbacks/calldata_rollback.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDFCMBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwYXNzCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGZvbyhzZWxmLCBhLCBiKToKCQlwcmludCgnY29udHJhY3QgdG8uZm9vJykKCQlnbC52bS5Vc2VyRXJyb3IuaW1tZWRpYXRlKHsnZXJyb3InOiAnc29tZV9lcnJvcicsICdjb2RlJzogYSArIGJ9KQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/rollbacks/calldata_rollback.0_0.hash b/tests/cases/stable/py/rollbacks/calldata_rollback.0_0.hash deleted file mode 100644 index cc56b3ea8..000000000 --- a/tests/cases/stable/py/rollbacks/calldata_rollback.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDGogBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwYXNzCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG1haW4oc2VsZiwgYWRkcjogQWRkcmVzcyk6CgkJcHJpbnQoJ2NvbnRyYWN0IGZyb20ubWFpbicpCgkJdHJ5OgoJCQlyZXMgPSBnbC5jb250cmFjdC5nZXRfYXQoYWRkcikudmlldygpLmZvbygxLCAyKS5nZXQoKQoJCWV4Y2VwdCBnbC52bS5Vc2VyRXJyb3IgYXMgcjoKCQkJcHJpbnQoJ2hhbmRsZWQnLCByLmRhdGEpCgkJZWxzZToKCQkJcHJpbnQocmVzKQoJCQlleGl0KDEpCgAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/rollbacks/calldata_rollback.0_0_0.hash b/tests/cases/stable/py/rollbacks/calldata_rollback.0_0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/rollbacks/calldata_rollback.0_0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/py/rollbacks/nondet.0.hash b/tests/cases/stable/py/rollbacks/nondet.0.hash deleted file mode 100644 index a4812bc9e..000000000 --- a/tests/cases/stable/py/rollbacks/nondet.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDGGsBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQl0cnk6CgoJCQlkZWYgcnVuKCk6CgkJCQlnbC52bS5Vc2VyRXJyb3IuaW1tZWRpYXRlKCJuYWgsIEkgd29uJ3QgZXhlY3V0ZSIpCgoJCQlyZXMgPSBnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKHJ1bikuZ2V0KCkKCQlleGNlcHQgZ2wudm0uVXNlckVycm9yIGFzIHI6CgkJCXByaW50KCdoYW5kbGVkJywgci5kYXRhKQoJCWVsc2U6CgkJCXByaW50KHJlcykKCQkJZXhpdCgxKQoAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/rollbacks/simple.0.hash b/tests/cases/stable/py/rollbacks/simple.0.hash deleted file mode 100644 index c6abb80cb..000000000 --- a/tests/cases/stable/py/rollbacks/simple.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQmkAW5haCwgSSB3b24ndCBleGVjdXRlABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDDsgAAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlnbC52bS5Vc2VyRXJyb3IuaW1tZWRpYXRlKCJuYWgsIEkgd29uJ3QgZXhlY3V0ZSIpCgAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/sandbox/det/s/assign-json.0.hash b/tests/cases/stable/py/sandbox/det/s/assign-json.0.hash deleted file mode 100644 index 353d9f3ad..000000000 --- a/tests/cases/stable/py/sandbox/det/s/assign-json.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDFCABAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmLCBldjogc3RyKToKCQlnbGIgPSBnbG9iYWxzKCkKCQlwcmludChmJ3tnbC52bS5zcGF3bl9zYW5kYm94KGxhbWJkYTogZXZhbChldiwgZ2xiKSl9JykKCQlwcmludChqc29uLmxvYWRzLl9fbmFtZV9fKQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/sandbox/det/s/assign-json.0_0.hash b/tests/cases/stable/py/sandbox/det/s/assign-json.0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/sandbox/det/s/assign-json.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/py/sandbox/det/s/exit.0.hash b/tests/cases/stable/py/sandbox/det/s/exit.0.hash deleted file mode 100644 index 353d9f3ad..000000000 --- a/tests/cases/stable/py/sandbox/det/s/exit.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDFCABAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmLCBldjogc3RyKToKCQlnbGIgPSBnbG9iYWxzKCkKCQlwcmludChmJ3tnbC52bS5zcGF3bl9zYW5kYm94KGxhbWJkYTogZXZhbChldiwgZ2xiKSl9JykKCQlwcmludChqc29uLmxvYWRzLl9fbmFtZV9fKQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/sandbox/det/s/exit.0_0.hash b/tests/cases/stable/py/sandbox/det/s/exit.0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/sandbox/det/s/exit.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/py/sandbox/det/s/print.0.hash b/tests/cases/stable/py/sandbox/det/s/print.0.hash deleted file mode 100644 index 353d9f3ad..000000000 --- a/tests/cases/stable/py/sandbox/det/s/print.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDFCABAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmLCBldjogc3RyKToKCQlnbGIgPSBnbG9iYWxzKCkKCQlwcmludChmJ3tnbC52bS5zcGF3bl9zYW5kYm94KGxhbWJkYTogZXZhbChldiwgZ2xiKSl9JykKCQlwcmludChqc29uLmxvYWRzLl9fbmFtZV9fKQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/sandbox/det/s/print.0_0.hash b/tests/cases/stable/py/sandbox/det/s/print.0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/sandbox/det/s/print.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/py/sandbox/det/s/rollback.0.hash b/tests/cases/stable/py/sandbox/det/s/rollback.0.hash deleted file mode 100644 index 353d9f3ad..000000000 --- a/tests/cases/stable/py/sandbox/det/s/rollback.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDFCABAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmLCBldjogc3RyKToKCQlnbGIgPSBnbG9iYWxzKCkKCQlwcmludChmJ3tnbC52bS5zcGF3bl9zYW5kYm94KGxhbWJkYTogZXZhbChldiwgZ2xiKSl9JykKCQlwcmludChqc29uLmxvYWRzLl9fbmFtZV9fKQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/sandbox/det/s/rollback.0_0.hash b/tests/cases/stable/py/sandbox/det/s/rollback.0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/sandbox/det/s/rollback.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/py/sandbox/det/s/sandbox.0.hash b/tests/cases/stable/py/sandbox/det/s/sandbox.0.hash deleted file mode 100644 index 353d9f3ad..000000000 --- a/tests/cases/stable/py/sandbox/det/s/sandbox.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDFCABAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmLCBldjogc3RyKToKCQlnbGIgPSBnbG9iYWxzKCkKCQlwcmludChmJ3tnbC52bS5zcGF3bl9zYW5kYm94KGxhbWJkYTogZXZhbChldiwgZ2xiKSl9JykKCQlwcmludChqc29uLmxvYWRzLl9fbmFtZV9fKQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/sandbox/det/s/sandbox.0_0.hash b/tests/cases/stable/py/sandbox/det/s/sandbox.0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/sandbox/det/s/sandbox.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/py/sandbox/det/sandbox_write.0.hash b/tests/cases/stable/py/sandbox/det/sandbox_write.0.hash deleted file mode 100644 index 4068b6625..000000000 --- a/tests/cases/stable/py/sandbox/det/sandbox_write.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAB0VowI3LUbDran4l8dNNJu/4ORQx5gWfJ9YD42vhd71fpbD6gAAAACDAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF57oAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMC4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhecAAAAAgxhyAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0IHU4CgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJY291bnRlcjogdTgKCglkZWYgX19pbml0X18oc2VsZik6CgkJcHJpbnQoZidoZWxsbyB3b3JsZCB7c2VsZi5jb3VudGVyfScpCgoJCWRlZiBzYigpOgoJCQlzZWxmLmNvdW50ZXIgKz0gMQoKCQlwcmludChmJ2NvdW50ZXIgYmVmb3JlOiB7c2VsZi5jb3VudGVyfScpCgkJZ2wudm0uc3Bhd25fc2FuZGJveChzYiwgYWxsb3dfd3JpdGVfb3BzPVRydWUpCgkJcHJpbnQoZidjb3VudGVyIGFmdGVyOiB7c2VsZi5jb3VudGVyfScpCgAAAAAAAAAAAAAF diff --git a/tests/cases/stable/py/sandbox/non-det/s/assign-json.0.hash b/tests/cases/stable/py/sandbox/non-det/s/assign-json.0.hash deleted file mode 100644 index 27195b0fe..000000000 --- a/tests/cases/stable/py/sandbox/non-det/s/assign-json.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDFlwBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmLCBldjogc3RyKToKCQlkZWYgcnVuX25kZXQoKToKCQkJZ2xiID0gZ2xvYmFscygpCgkJCXByaW50KGYne2dsLnZtLnNwYXduX3NhbmRib3gobGFtYmRhOiBldmFsKGV2LCBnbGIpKX0nKQoJCQlwcmludChqc29uLmxvYWRzLl9fbmFtZV9fKQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKHJ1bl9uZGV0KQoF diff --git a/tests/cases/stable/py/sandbox/non-det/s/assign-json.0_0.hash b/tests/cases/stable/py/sandbox/non-det/s/assign-json.0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/sandbox/non-det/s/assign-json.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/py/sandbox/non-det/s/exit.0.hash b/tests/cases/stable/py/sandbox/non-det/s/exit.0.hash deleted file mode 100644 index 27195b0fe..000000000 --- a/tests/cases/stable/py/sandbox/non-det/s/exit.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDFlwBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmLCBldjogc3RyKToKCQlkZWYgcnVuX25kZXQoKToKCQkJZ2xiID0gZ2xvYmFscygpCgkJCXByaW50KGYne2dsLnZtLnNwYXduX3NhbmRib3gobGFtYmRhOiBldmFsKGV2LCBnbGIpKX0nKQoJCQlwcmludChqc29uLmxvYWRzLl9fbmFtZV9fKQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKHJ1bl9uZGV0KQoF diff --git a/tests/cases/stable/py/sandbox/non-det/s/exit.0_0.hash b/tests/cases/stable/py/sandbox/non-det/s/exit.0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/sandbox/non-det/s/exit.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/py/sandbox/non-det/s/print.0.hash b/tests/cases/stable/py/sandbox/non-det/s/print.0.hash deleted file mode 100644 index 27195b0fe..000000000 --- a/tests/cases/stable/py/sandbox/non-det/s/print.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDFlwBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmLCBldjogc3RyKToKCQlkZWYgcnVuX25kZXQoKToKCQkJZ2xiID0gZ2xvYmFscygpCgkJCXByaW50KGYne2dsLnZtLnNwYXduX3NhbmRib3gobGFtYmRhOiBldmFsKGV2LCBnbGIpKX0nKQoJCQlwcmludChqc29uLmxvYWRzLl9fbmFtZV9fKQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKHJ1bl9uZGV0KQoF diff --git a/tests/cases/stable/py/sandbox/non-det/s/print.0_0.hash b/tests/cases/stable/py/sandbox/non-det/s/print.0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/sandbox/non-det/s/print.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/py/sandbox/non-det/s/rollback.0.hash b/tests/cases/stable/py/sandbox/non-det/s/rollback.0.hash deleted file mode 100644 index 27195b0fe..000000000 --- a/tests/cases/stable/py/sandbox/non-det/s/rollback.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDFlwBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmLCBldjogc3RyKToKCQlkZWYgcnVuX25kZXQoKToKCQkJZ2xiID0gZ2xvYmFscygpCgkJCXByaW50KGYne2dsLnZtLnNwYXduX3NhbmRib3gobGFtYmRhOiBldmFsKGV2LCBnbGIpKX0nKQoJCQlwcmludChqc29uLmxvYWRzLl9fbmFtZV9fKQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKHJ1bl9uZGV0KQoF diff --git a/tests/cases/stable/py/sandbox/non-det/s/rollback.0_0.hash b/tests/cases/stable/py/sandbox/non-det/s/rollback.0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/py/sandbox/non-det/s/rollback.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/py/schemas/complex_types.0.hash b/tests/cases/stable/py/schemas/complex_types.0.hash deleted file mode 100644 index 2d3021c04..000000000 --- a/tests/cases/stable/py/schemas/complex_types.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDKGgCAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgppbXBvcnQgdHlwaW5nCgoKY2xhc3MgTXlURGljdCh0eXBpbmcuVHlwZWREaWN0KToKCWE6IGludAoJYjogc3RyCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJZGVmIF9faW5pdF9fKHNlbGYpOgoJCXBhc3MKCglAZ2wucHVibGljLndyaXRlCglkZWYgb3B0KAoJCXNlbGYsIGExOiBsaXN0IHwgTm9uZSwgYTI6IHR5cGluZy5VbmlvbltzdHIsIGJ5dGVzXSwgYTM6IHR5cGluZy5PcHRpb25hbFtzdHJdCgkpOgoJCXBhc3MKCglAZ2wucHVibGljLndyaXRlCglkZWYgbHN0KAoJCXNlbGYsIGExOiBsaXN0W3N0cl0sIGEyOiB0eXBpbmcuU2VxdWVuY2Vbc3RyXSwgYTM6IHR5cGluZy5NdXRhYmxlU2VxdWVuY2VbaW50XQoJKToKCQlwYXNzCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGRpY3QoCgkJc2VsZiwKCQlhMTogZGljdFtzdHIsIGludF0sCgkJYTI6IHR5cGluZy5NYXBwaW5nW3N0ciwgc3RyXSwKCQlhMzogdHlwaW5nLk11dGFibGVNYXBwaW5nW3N0ciwgaW50IHwgc3RyIHwgTm9uZV0sCgkpOgoJCXBhc3MKAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/py/schemas/complex_types.0_0.hash b/tests/cases/stable/py/schemas/complex_types.0_0.hash deleted file mode 100644 index 58efe808f..000000000 --- a/tests/cases/stable/py/schemas/complex_types.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQH0InsiY3RvciI6eyJwYXJhbXMiOltdLCJrd3BhcmFtcyI6e319LCJtZXRob2RzIjp7ImRpY3QiOnsicGFyYW1zIjpbWyJhMSIseyIkZGljdCI6ImludCJ9XSxbImEyIix7IiRkaWN0Ijoic3RyaW5nIn1dLFsiYTMiLHsiJGRpY3QiOnsiJG9yIjpbImludCIsInN0cmluZyIsIm51bGwiXX19XV0sImt3cGFyYW1zIjp7fSwicmVhZG9ubHkiOmZhbHNlLCJyZXQiOiJhbnkiLCJwYXlhYmxlIjpmYWxzZX0sImxzdCI6eyJwYXJhbXMiOltbImExIixbeyIkcmVwIjoic3RyaW5nIn1dXSxbImEyIixbeyIkcmVwIjoic3RyaW5nIn1dXSxbImEzIixbeyIkcmVwIjoiaW50In1dXV0sImt3cGFyYW1zIjp7fSwicmVhZG9ubHkiOmZhbHNlLCJyZXQiOiJhbnkiLCJwYXlhYmxlIjpmYWxzZX0sIm9wdCI6eyJwYXJhbXMiOltbImExIix7IiRvciI6WyJhcnJheSIsIm51bGwiXX1dLFsiYTIiLHsiJG9yIjpbInN0cmluZyIsImJ5dGVzIl19XSxbImEzIix7IiRvciI6WyJzdHJpbmciLCJudWxsIl19XV0sImt3cGFyYW1zIjp7fSwicmVhZG9ubHkiOmZhbHNlLCJyZXQiOiJhbnkiLCJwYXlhYmxlIjpmYWxzZX19fQAFBQ== diff --git a/tests/cases/stable/py/schemas/prim_types.0.hash b/tests/cases/stable/py/schemas/prim_types.0.hash deleted file mode 100644 index 9951e2083..000000000 --- a/tests/cases/stable/py/schemas/prim_types.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDGGMBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKaW1wb3J0IHR5cGluZwoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwYXNzCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGZvbyhzZWxmLCBhMTogaW50LCBhMjogTm9uZSwgYTM6IGJvb2wsIGE0OiBzdHIsIGE1OiBieXRlcywgYTY6IEFkZHJlc3MpOgoJCXBhc3MKCglAZ2wucHVibGljLndyaXRlCglkZWYgZXJhc2VkKHNlbGYsIGExOiBsaXN0LCBhMjogZGljdCwgYTM6IHR5cGluZy5BbnkpOgoJCXBhc3MKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/schemas/prim_types.0_0.hash b/tests/cases/stable/py/schemas/prim_types.0_0.hash deleted file mode 100644 index 521cc2e09..000000000 --- a/tests/cases/stable/py/schemas/prim_types.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQGUFXsiY3RvciI6eyJwYXJhbXMiOltdLCJrd3BhcmFtcyI6e319LCJtZXRob2RzIjp7ImVyYXNlZCI6eyJwYXJhbXMiOltbImExIiwiYXJyYXkiXSxbImEyIiwiZGljdCJdLFsiYTMiLCJhbnkiXV0sImt3cGFyYW1zIjp7fSwicmVhZG9ubHkiOmZhbHNlLCJyZXQiOiJhbnkiLCJwYXlhYmxlIjpmYWxzZX0sImZvbyI6eyJwYXJhbXMiOltbImExIiwiaW50Il0sWyJhMiIsIm51bGwiXSxbImEzIiwiYm9vbCJdLFsiYTQiLCJzdHJpbmciXSxbImE1IiwiYnl0ZXMiXSxbImE2IiwiYWRkcmVzcyJdXSwia3dwYXJhbXMiOnt9LCJyZWFkb25seSI6ZmFsc2UsInJldCI6ImFueSIsInBheWFibGUiOmZhbHNlfX19AAUF diff --git a/tests/cases/stable/py/schemas/ret-float.0.hash b/tests/cases/stable/py/schemas/ret-float.0.hash deleted file mode 100644 index 265a369c0..000000000 --- a/tests/cases/stable/py/schemas/ret-float.0.hash +++ /dev/null @@ -1 +0,0 @@ -LRFcZXhpdF9jb2RlIDEAFRWjAroAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELAAAAAIMKBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhee6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAuGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnAAAAAIMQ3gAAACMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJZGVmIF9faW5pdF9fKHNlbGYsIGZvbywgYmFyKToKCQlwYXNzCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGZvbyhzZWxmKSAtPiBmbG9hdDoKCQlyZXR1cm4gMC4wCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/schemas/ret-float.0_0.hash b/tests/cases/stable/py/schemas/ret-float.0_0.hash deleted file mode 100644 index 131eae252..000000000 --- a/tests/cases/stable/py/schemas/ret-float.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LRFcZXhpdF9jb2RlIDEABQU= diff --git a/tests/cases/stable/py/schemas/ret-tuple.0.hash b/tests/cases/stable/py/schemas/ret-tuple.0.hash deleted file mode 100644 index 6874be6f8..000000000 --- a/tests/cases/stable/py/schemas/ret-tuple.0.hash +++ /dev/null @@ -1 +0,0 @@ -LRFcZXhpdF9jb2RlIDEAFRWjAroAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELAAAAAIMKBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhee6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAuGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnAAAAAIMULwEAACMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJZGVmIF9faW5pdF9fKHNlbGYsIGZvbywgYmFyKToKCQlwYXNzCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGZvbyhzZWxmKSAtPiB0dXBsZVtpbnQsIGludF06CgkJcmV0dXJuICgxLCAyKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBiYXIoc2VsZikgLT4gdHVwbGVbaW50LCAuLi5dOgoJCXJldHVybiAoMSwpCgAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/py/schemas/ret-tuple.0_0.hash b/tests/cases/stable/py/schemas/ret-tuple.0_0.hash deleted file mode 100644 index a47bd9db2..000000000 --- a/tests/cases/stable/py/schemas/ret-tuple.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQHkD3siY3RvciI6eyJwYXJhbXMiOltbImZvbyIsImFueSJdLFsiYmFyIiwiYW55Il1dLCJrd3BhcmFtcyI6e319LCJtZXRob2RzIjp7ImJhciI6eyJwYXJhbXMiOltdLCJrd3BhcmFtcyI6e30sInJlYWRvbmx5IjpmYWxzZSwicmV0IjpbeyIkcmVwIjoiaW50In1dLCJwYXlhYmxlIjpmYWxzZX0sImZvbyI6eyJwYXJhbXMiOltdLCJrd3BhcmFtcyI6e30sInJlYWRvbmx5IjpmYWxzZSwicmV0IjpbImludCIsImludCJdLCJwYXlhYmxlIjpmYWxzZX19fQAFBQ== diff --git a/tests/cases/stable/py/schemas/ret.0.hash b/tests/cases/stable/py/schemas/ret.0.hash deleted file mode 100644 index ccbce72cb..000000000 --- a/tests/cases/stable/py/schemas/ret.0.hash +++ /dev/null @@ -1 +0,0 @@ -LRFcZXhpdF9jb2RlIDEAFRWjAroAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELAAAAAIMKBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhee6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAuGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnAAAAAIMcoQEAACMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJZGVmIF9faW5pdF9fKHNlbGYsIGZvbywgYmFyKToKCQlwYXNzCgoJQGdsLnB1YmxpYy52aWV3CglkZWYgZm9vKHNlbGYpOgoJCXBhc3MKCglAZ2wucHVibGljLndyaXRlCglkZWYgcG9zKHNlbGYsIHgsIHkpOgoJCXBhc3MKCglAZ2wucHVibGljLndyaXRlCglkZWYga3coc2VsZiwgKiwgeCwgeSk6CgkJcGFzcwoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtaXhlZChzZWxmLCBhLCBiLCAqLCB4LCB5KToKCQlwYXNzCgoJQGdsLnB1YmxpYy53cml0ZS5wYXlhYmxlCglkZWYgcGF5YWJsZShzZWxmKToKCQlwYXNzCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/schemas/ret.0_0.hash b/tests/cases/stable/py/schemas/ret.0_0.hash deleted file mode 100644 index 5f76c4b8b..000000000 --- a/tests/cases/stable/py/schemas/ret.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQHsIXsiY3RvciI6eyJwYXJhbXMiOltbImZvbyIsImFueSJdLFsiYmFyIiwiYW55Il1dLCJrd3BhcmFtcyI6e319LCJtZXRob2RzIjp7ImZvbyI6eyJwYXJhbXMiOltdLCJrd3BhcmFtcyI6e30sInJlYWRvbmx5Ijp0cnVlLCJyZXQiOiJhbnkifSwia3ciOnsicGFyYW1zIjpbXSwia3dwYXJhbXMiOnsieCI6ImFueSIsInkiOiJhbnkifSwicmVhZG9ubHkiOmZhbHNlLCJyZXQiOiJhbnkiLCJwYXlhYmxlIjpmYWxzZX0sIm1peGVkIjp7InBhcmFtcyI6W1siYSIsImFueSJdLFsiYiIsImFueSJdXSwia3dwYXJhbXMiOnsieCI6ImFueSIsInkiOiJhbnkifSwicmVhZG9ubHkiOmZhbHNlLCJyZXQiOiJhbnkiLCJwYXlhYmxlIjpmYWxzZX0sInBheWFibGUiOnsicGFyYW1zIjpbXSwia3dwYXJhbXMiOnt9LCJyZWFkb25seSI6ZmFsc2UsInJldCI6ImFueSIsInBheWFibGUiOnRydWV9LCJwb3MiOnsicGFyYW1zIjpbWyJ4IiwiYW55Il0sWyJ5IiwiYW55Il1dLCJrd3BhcmFtcyI6e30sInJlYWRvbmx5IjpmYWxzZSwicmV0IjoiYW55IiwicGF5YWJsZSI6ZmFsc2V9fX0ABQU= diff --git a/tests/cases/stable/py/schemas/trivial.0.hash b/tests/cases/stable/py/schemas/trivial.0.hash deleted file mode 100644 index ccbce72cb..000000000 --- a/tests/cases/stable/py/schemas/trivial.0.hash +++ /dev/null @@ -1 +0,0 @@ -LRFcZXhpdF9jb2RlIDEAFRWjAroAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELAAAAAIMKBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhee6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAuGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnAAAAAIMcoQEAACMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJZGVmIF9faW5pdF9fKHNlbGYsIGZvbywgYmFyKToKCQlwYXNzCgoJQGdsLnB1YmxpYy52aWV3CglkZWYgZm9vKHNlbGYpOgoJCXBhc3MKCglAZ2wucHVibGljLndyaXRlCglkZWYgcG9zKHNlbGYsIHgsIHkpOgoJCXBhc3MKCglAZ2wucHVibGljLndyaXRlCglkZWYga3coc2VsZiwgKiwgeCwgeSk6CgkJcGFzcwoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtaXhlZChzZWxmLCBhLCBiLCAqLCB4LCB5KToKCQlwYXNzCgoJQGdsLnB1YmxpYy53cml0ZS5wYXlhYmxlCglkZWYgcGF5YWJsZShzZWxmKToKCQlwYXNzCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/schemas/trivial.0_0.hash b/tests/cases/stable/py/schemas/trivial.0_0.hash deleted file mode 100644 index 5f76c4b8b..000000000 --- a/tests/cases/stable/py/schemas/trivial.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQHsIXsiY3RvciI6eyJwYXJhbXMiOltbImZvbyIsImFueSJdLFsiYmFyIiwiYW55Il1dLCJrd3BhcmFtcyI6e319LCJtZXRob2RzIjp7ImZvbyI6eyJwYXJhbXMiOltdLCJrd3BhcmFtcyI6e30sInJlYWRvbmx5Ijp0cnVlLCJyZXQiOiJhbnkifSwia3ciOnsicGFyYW1zIjpbXSwia3dwYXJhbXMiOnsieCI6ImFueSIsInkiOiJhbnkifSwicmVhZG9ubHkiOmZhbHNlLCJyZXQiOiJhbnkiLCJwYXlhYmxlIjpmYWxzZX0sIm1peGVkIjp7InBhcmFtcyI6W1siYSIsImFueSJdLFsiYiIsImFueSJdXSwia3dwYXJhbXMiOnsieCI6ImFueSIsInkiOiJhbnkifSwicmVhZG9ubHkiOmZhbHNlLCJyZXQiOiJhbnkiLCJwYXlhYmxlIjpmYWxzZX0sInBheWFibGUiOnsicGFyYW1zIjpbXSwia3dwYXJhbXMiOnt9LCJyZWFkb25seSI6ZmFsc2UsInJldCI6ImFueSIsInBheWFibGUiOnRydWV9LCJwb3MiOnsicGFyYW1zIjpbWyJ4IiwiYW55Il0sWyJ5IiwiYW55Il1dLCJrd3BhcmFtcyI6e30sInJlYWRvbmx5IjpmYWxzZSwicmV0IjoiYW55IiwicGF5YWJsZSI6ZmFsc2V9fX0ABQU= diff --git a/tests/cases/stable/runners/dup-dependency.0.hash b/tests/cases/stable/runners/dup-dependency.0.hash deleted file mode 100644 index 422be9d1c..000000000 --- a/tests/cases/stable/runners/dup-dependency.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDEN8AAAAjIHsKIyAgICJTZXEiOiBbCiMgICAgIHsgIkRlcGVuZHMiOiAic29mdGZsb2F0OnRlc3QiIH0sCiMgICAgIHsgIkRlcGVuZHMiOiAic29mdGZsb2F0OnRlc3QiIH0sCiMgICAgIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQojICAgXQojIH0KCmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCgpwcmludCgnSSBhbSBvaycpCmV4aXQoMCkKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/runners/env-template.0.hash b/tests/cases/stable/runners/env-template.0.hash deleted file mode 100644 index c8796404e..000000000 --- a/tests/cases/stable/runners/env-template.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDDtUAAAAjIHsKIyAgICJTZXEiOiBbCiMgICAgIHsgIkFkZEVudiI6IHsgIm5hbWUiOiAiWCIsICJ2YWwiOiAiMSIgfSB9LAojICAgICB7ICJBZGRFbnYiOiB7ICJuYW1lIjogIlgiLCAidmFsIjogIiR7WH06MiIgfSB9LAojICAgICB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KIyAgIF0KIyB9CgppbXBvcnQgb3MKCnByaW50KG9zLmVudmlyb25bJ1gnXSkKZXhpdCgwKQoAAAAAAAAABQ== diff --git a/tests/cases/stable/runners/malformed_runner.0.hash b/tests/cases/stable/runners/malformed_runner.0.hash deleted file mode 100644 index 0d05fa3dc..000000000 --- a/tests/cases/stable/runners/malformed_runner.0.hash +++ /dev/null @@ -1 +0,0 @@ -LRGEAWludmFsaWRfY29udHJhY3QADRWjAuGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnAAAAAIMCGwAAACMgeyAiRm9vIjogImJhciIgfQpleGl0KDApCgAF diff --git a/tests/cases/stable/runners/no_runner.0.hash b/tests/cases/stable/runners/no_runner.0.hash deleted file mode 100644 index b5be56f6e..000000000 --- a/tests/cases/stable/runners/no_runner.0.hash +++ /dev/null @@ -1 +0,0 @@ -LRG0AmludmFsaWRfY29udHJhY3QgYWJzZW50X3J1bm5lcl9jb21tZW50AAUF diff --git a/tests/cases/stable/runners/zip/no-zip.0.hash b/tests/cases/stable/runners/zip/no-zip.0.hash deleted file mode 100644 index d044d0993..000000000 --- a/tests/cases/stable/runners/zip/no-zip.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDDKsAAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwcmludCgnaGVsbG8gd29ybGQnKQoAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/self-run/datetime.0.hash b/tests/cases/stable/self-run/datetime.0.hash deleted file mode 100644 index 48066a940..000000000 --- a/tests/cases/stable/self-run/datetime.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDCF4AAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKaW1wb3J0IGRhdGV0aW1lCgpwcmludChkYXRldGltZS5kYXRldGltZS5ub3coKSkKCmV4aXQoMCkKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/self-run/floats.0.hash b/tests/cases/stable/self-run/floats.0.hash deleted file mode 100644 index 052b7aa11..000000000 --- a/tests/cases/stable/self-run/floats.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDNkEDAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgbWF0aAoKaW1wb3J0IG9wZXJhdG9yCgpkYXRhOiBsaXN0W2Zsb2F0XSA9IFsKCW1hdGgubmFuLAoJbWF0aC5pbmYsCgktbWF0aC5pbmYsCgkxLjQxNDIxMzU2MjM3LAoJLTEuNDE0MjEzNTYyMzcsCgkxLjAsCgktMSwKCTFlNSwKCS0xZTUsCgkwLjAsCgktMC4wLApdCgppbXBvcnQgc3RydWN0CmltcG9ydCBudW1weSBhcyBucAoKZm9yIHggaW4gZGF0YToKCXByaW50KCduZXcgeCcpCglmb3IgeSBpbiBkYXRhOgoJCWZvciBvcCBpbiBbbWF0aC5mbG9vciwgbWF0aC5jZWlsLCBtYXRoLnNxcnQsIG1hdGguc2luLCBpbnQsIG1hdGguZXhwXToKCQkJdHJ5OgoJCQkJcmVzID0gb3AoeCkKCQkJCWlmIG1hdGguaXNuYW4ocmVzKToKCQkJCQlyZXMgPSBtYXRoLm5hbgoJCQkJcyA9IHN0cnVjdC5wYWNrKCc+ZCcsIHJlcykKCQkJCXByaW50KGYnXHR7eDouNWZ9IHtvcH0ge3JlczouNWZ9IHtzLmhleCgpfScpCgkJCWV4Y2VwdDoKCQkJCXBhc3MKCQlwcmludCgnXHRuZXcgeScpCgkJZm9yIG9wIGluIFsKCQkJb3BlcmF0b3IuYWRkLAoJCQlvcGVyYXRvci5zdWIsCgkJCW9wZXJhdG9yLm11bCwKCQkJb3BlcmF0b3IudHJ1ZWRpdiwKCQldOiAgIyBvcGVyYXRvci5wb3cKCQkJdHJ5OgoJCQkJcmVzID0gb3AoeCwgeSkKCQkJCWlmIG1hdGguaXNuYW4ocmVzKToKCQkJCQlyZXMgPSBtYXRoLm5hbgoJCQkJcyA9IHN0cnVjdC5wYWNrKCc+ZCcsIHJlcykKCQkJCXByaW50KGYnXHRcdHt4Oi41Zn0ge29wfSB7eTouNWZ9IHtyZXM6LjVmfSB7cy5oZXgoKX0nKQoJCQlleGNlcHQ6CgkJCQlwYXNzCgpleGl0KDApCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/self-run/formats.0.hash b/tests/cases/stable/self-run/formats.0.hash deleted file mode 100644 index eec520be3..000000000 --- a/tests/cases/stable/self-run/formats.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDJB0CAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKZnJvbSBnZW5sYXllci5zdG9yYWdlLl9pbnRlcm5hbC5nZW5lcmF0ZSBpbXBvcnQgZ2VuZXJhdGVfc3RvcmFnZQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgQWRkcmVzcwoKCkBnZW5lcmF0ZV9zdG9yYWdlCmNsYXNzIFRlc3Q6CglhcnI6IGdsLkR5bkFycmF5W3N0cl0KCW1hcDogZ2wuVHJlZU1hcFtzdHIsIE5vbmVdCgoKYWRkciA9IEFkZHJlc3MoYidceGEyJyAqIDIwKQpwcmludChhZGRyKQpwcmludChmJ3thZGRyfScpCnByaW50KGYne2FkZHIhcn0nKQpwcmludChmJ3thZGRyIXN9JykKcHJpbnQoZid7YWRkcjpjZH0nKQpwcmludChmJ3thZGRyOmI2NH0nKQpwcmludChmJ3thZGRyOnh9JykKcHJpbnQoZid7YWRkcjp9JykKCnQgPSBUZXN0KCkKdC5hcnIuZXh0ZW5kKFsnMScsICcyJywgJzMnXSkKdC5tYXAudXBkYXRlKHsnMSc6IE5vbmUsICc0JzogTm9uZX0pCnByaW50KGYne3QuYXJyfScpCnByaW50KGYne3QubWFwfScpCmV4aXQoMCkKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/self-run/issue_163.0.hash b/tests/cases/stable/self-run/issue_163.0.hash deleted file mode 100644 index b171a0f9b..000000000 --- a/tests/cases/stable/self-run/issue_163.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDFCgBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKZnJvbSBnZW5sYXllci5zdG9yYWdlLl9pbnRlcm5hbC5nZW5lcmF0ZSBpbXBvcnQgZ2VuZXJhdGVfc3RvcmFnZQoKCkBnZW5lcmF0ZV9zdG9yYWdlCmNsYXNzIFByOgoJeDogZ2wuVHJlZU1hcFtzdHIsIHN0cl0KCgphID0gUHIoKQoKdHJ5OgoJYS54ID0geyd4JzogJ3knfQpleGNlcHQgQXNzZXJ0aW9uRXJyb3IgYXMgZToKCXByaW50KCplLmFyZ3MpCgpleGl0KDApCgAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/self-run/module/np.0.hash b/tests/cases/stable/self-run/module/np.0.hash deleted file mode 100644 index fdc7e4cac..000000000 --- a/tests/cases/stable/self-run/module/np.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDCGsAAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgbnVtcHkgYXMgbnAKCnByaW50KG5wLmFycmF5KFsxLCAyLCAzXSwgZHR5cGU9aW50KSAqKiAyKQpleGl0KDApCgAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/self-run/module/pil.0.hash b/tests/cases/stable/self-run/module/pil.0.hash deleted file mode 100644 index 2106a4c29..000000000 --- a/tests/cases/stable/self-run/module/pil.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDMPkCAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQpmcm9tIFBJTCBpbXBvcnQgSW1hZ2UKCmltcG9ydCBpbwoKaW1fZGF0YSA9IGInXHg4OVBOR1xyXG5ceDFhXG5ceDAwXHgwMFx4MDBccklIRFJceDAwXHgwMFx4MDAkXHgwMFx4MDBceDAwXHgxNVx4MDFceDAzXHgwMFx4MDBceDAwXHgxNFx4ZThceGRlXHhkM1x4MDBceDAwXHgwMFx4MDZQTFRFXHhmZlx4ZmZceGZmXHgwMFx4MDBceDAwVVx4YzJceGQzflx4MDBceDAwXHgwMFRJREFUeFx4OWNjYEBceDAyXHgwZVx4MGNceDBjXHgxY1x4MGNceDBjXHgxZVx4Y2NceDBmeFx4ODBceGE0XHhhM1x4MDJceDkwXHg4Y1x4MDBceDkzXHgwMVAyXHg4MVx4OGJceDgxXHhhMVx4YzBceGYxXHg4MFx4MTBceDAzQ1x4ODJjXHg4M1x4MTBceDg4XHhlZCBceDA0XHgxNlx4MDdceDkxXHg4YVx4MDJceDEwXHhkMlx4MDhEclx4ZDhceDAxTVBceGU0UVx4MDJceDkyXG4sSiBjXHg5OVx4MTRceDE4XHgxOHhceGMwXHhiNlx4YjAgLFx4MDRceDAwXHg4NFx4YWJceDBjXHhjYVx4MDJceDhlKlx4YjBceDAwXHgwMFx4MDBceDAwSUVORFx4YWVCYFx4ODInCgppbWcgPSBJbWFnZS5vcGVuKGlvLkJ5dGVzSU8oaW1fZGF0YSkpCmlmIGltZy5tb2RlICE9ICdSR0InOgoJaW1nID0gaW1nLmNvbnZlcnQoJ1JHQicpCgpwaXhlbHMgPSBsaXN0KGltZy5nZXRkYXRhKCkpCgpyZXMgPSBzZXQoKQoKZm9yIGkgaW4gcGl4ZWxzOgoJcmVzLmFkZChpKQoKcHJpbnQobGlzdChzb3J0ZWQocmVzKSkpCgpleGl0KDApCgAAAAU= diff --git a/tests/cases/stable/self-run/re.0.hash b/tests/cases/stable/self-run/re.0.hash deleted file mode 100644 index ead28ebeb..000000000 --- a/tests/cases/stable/self-run/re.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDJCwCAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKaW1wb3J0IHJlCgphc3NlcnQgcmUubWF0Y2goJyhhYnxiYSknLCAnYWInKS5zcGFuKCkgPT0gKDAsIDIpCmFzc2VydCByZS5tYXRjaCgnKGFifGJhKScsICdiYScpLnNwYW4oKSA9PSAoMCwgMikKYXNzZXJ0IHJlLm1hdGNoKCcoYWJjfGJhY3xjYXxjYiknLCAnYWJjJykuc3BhbigpID09ICgwLCAzKQphc3NlcnQgcmUubWF0Y2goJyhhYmN8YmFjfGNhfGNiKScsICdiYWMnKS5zcGFuKCkgPT0gKDAsIDMpCmFzc2VydCByZS5tYXRjaCgnKGFiY3xiYWN8Y2F8Y2IpJywgJ2NhJykuc3BhbigpID09ICgwLCAyKQphc3NlcnQgcmUubWF0Y2goJyhhYmN8YmFjfGNhfGNiKScsICdjYicpLnNwYW4oKSA9PSAoMCwgMikKYXNzZXJ0IHJlLm1hdGNoKCcoKGEpfChiKXwoYykpJywgJ2EnKS5zcGFuKCkgPT0gKDAsIDEpCmFzc2VydCByZS5tYXRjaCgnKChhKXwoYil8KGMpKScsICdiJykuc3BhbigpID09ICgwLCAxKQphc3NlcnQgcmUubWF0Y2goJygoYSl8KGIpfChjKSknLCAnYycpLnNwYW4oKSA9PSAoMCwgMSkKCmV4aXQoMCkKAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/self-run/typing_is_ok.0.hash b/tests/cases/stable/self-run/typing_is_ok.0.hash deleted file mode 100644 index 1b057c1ae..000000000 --- a/tests/cases/stable/self-run/typing_is_ok.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDKpkCAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKIyBmcm9tIF9fZnV0dXJlX18gaW1wb3J0IGFubm90YXRpb25zCgppbXBvcnQgdHlwaW5nCmltcG9ydCB0eXBlcwoKCmNsYXNzIEZvb1tYXToKCWE6IFgKCgpkZWYgdHN0KHgpOgoJcHJpbnQoZic9PT0ge3guX19uYW1lX199JykKCXByaW50KHR5cGUoeCkpCglwcmludCh4KQoJaWYgaXNpbnN0YW5jZSh4LCB0eXBlcy5HZW5lcmljQWxpYXMpOgoJCXByaW50KGYnb3JpZ2luPXt4Ll9fb3JpZ2luX199JykKCQlwcmludChmJ2FyZ3M9e3guX19hcmdzX199JykKCWVsaWYgaXNpbnN0YW5jZSh4LCB0eXBpbmcuX0dlbmVyaWNBbGlhcyk6ICAjIHR5cGU6IGlnbm9yZQoJCXByaW50KGYnb3JpZ2luPXt4Ll9fb3JpZ2luX199JykKCQlwcmludChmJ2FyZ3M9e3guX19hcmdzX199JykKCWlmIG5vdCBpc2luc3RhbmNlKHgsIHR5cGVzLkdlbmVyaWNBbGlhcyk6CgkJZm9yIGssIHYgaW4gdHlwaW5nLmdldF90eXBlX2hpbnRzKHgpLml0ZW1zKCk6CgkJCWlmIGlzaW5zdGFuY2UodiwgdHlwaW5nLlR5cGVWYXIpOgoJCQkJdiA9IHYuX19uYW1lX18KCQkJcHJpbnQoZidcdHtrfToge3Z9JykKCgp0c3QoRm9vKQoKdHN0KGxpc3Rbc3RyXSkKCgpjbGFzcyBUZXN0OgoJZm9vOiBGb29bc3RyXQoKCnRzdChUZXN0KQpleGl0KDApCgAAAAU= diff --git a/tests/cases/stable/storage/alloc_generic.0.hash b/tests/cases/stable/storage/alloc_generic.0.hash deleted file mode 100644 index 17def795e..000000000 --- a/tests/cases/stable/storage/alloc_generic.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDEhABAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKZnJvbSBnZW5sYXllci5zdG9yYWdlIGltcG9ydCBhbGxvdwpmcm9tIGRhdGFjbGFzc2VzIGltcG9ydCBkYXRhY2xhc3MKCgpAYWxsb3cKQGRhdGFjbGFzcwpjbGFzcyBUZXN0W1RdOgoJZm9vOiBUCgoKdHN0ID0gZ2wuc3RvcmFnZS5pbm1lbV9hbGxvY2F0ZShUZXN0W3N0cl0sICcxMjMnKQpwcmludCh0c3QpCgpleGl0KDApCgAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/storage/alloc_generic_err.0.hash b/tests/cases/stable/storage/alloc_generic_err.0.hash deleted file mode 100644 index 91f631757..000000000 --- a/tests/cases/stable/storage/alloc_generic_err.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDHKgBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKZnJvbSBnZW5sYXllci5zdG9yYWdlIGltcG9ydCBhbGxvdwpmcm9tIGRhdGFjbGFzc2VzIGltcG9ydCBkYXRhY2xhc3MKZnJvbSBnZW5sYXllci5zdG9yYWdlLl9pbnRlcm5hbC5nZW5lcmF0ZSBpbXBvcnQgZ2VuZXJhdGVfc3RvcmFnZQoKCkBhbGxvdwpAZGF0YWNsYXNzCmNsYXNzIFRlc3RbVF06Cglmb286IFQKCgpAZ2VuZXJhdGVfc3RvcmFnZQpjbGFzcyBCYXI6Cgl0OiBUZXN0W3N0cl0KCgp0cnk6Cgl0c3QgPSBUZXN0KCcxMjMnKQoJcHJpbnQodHN0KQpleGNlcHQgRXhjZXB0aW9uIGFzIGU6CglwcmludChlKQoJZm9yIG4gaW4gZS5fX25vdGVzX186CgkJcHJpbnQobikKCmV4aXQoMCkKAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/storage/base.0.hash b/tests/cases/stable/storage/base.0.hash deleted file mode 100644 index 05ecc3fda..000000000 --- a/tests/cases/stable/storage/base.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDJlgCAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKZnJvbSBnZW5sYXllci5zdG9yYWdlIGltcG9ydCBhbGxvdwpmcm9tIGdlbmxheWVyLnN0b3JhZ2UuX2ludGVybmFsLmdlbmVyYXRlIGltcG9ydCBnZW5lcmF0ZV9zdG9yYWdlCgoKQGFsbG93CmNsYXNzIFRlc3Q6Cglmb286IGk2NAoJYmFyOiBpNjQKCXN0OiBzdHIKCglkZWYgYWJjKHNlbGYpOgoJCXJldHVybiBzZWxmLmZvbwoKCkBnZW5lcmF0ZV9zdG9yYWdlCmNsYXNzIENvbXBvc2l0ZToKCWE6IFRlc3QKCWI6IFRlc3QKCgp0c3QgPSBDb21wb3NpdGUoKQoKc3Rvcl9tYW4gPSB0c3QuX3N0b3JhZ2Vfc2xvdC5tYW5hZ2VyICAjIHR5cGU6IGlnbm9yZQoKdHN0LmEuZm9vID0gNjU1MzUKdHN0LmEuYmFyID0gMioqMzIKdHN0LmEuc3QgPSAnMTIzJwp0c3QuYi5mb28gPSAxMwp0c3QuYi5zdCA9ICczMjEnCgpzdG9yX21hbi5kZWJ1ZygpCnByaW50KHRzdC5hLnN0LCB0c3QuYi5zdCkKCnRzdC5hID0gdHN0LmIKCnN0b3JfbWFuLmRlYnVnKCkKcHJpbnQodHN0LmEuc3QsIHRzdC5iLnN0KQoKZXhpdCgwKQoAAAAABQ== diff --git a/tests/cases/stable/storage/bootstrapper.0.hash b/tests/cases/stable/storage/bootstrapper.0.hash deleted file mode 100644 index 18830c28b..000000000 --- a/tests/cases/stable/storage/bootstrapper.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAB0VowKiRi7bAKscdB3IgeOx6Og55TTHvN8qFSvIb65Eo5cweQAAAACDCogAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF57oAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACD4AHjDQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCmltcG9ydCB0eXBpbmcKCmltcG9ydCBnZW5sYXllciBhcyBnbAoKX0NBTENfTUFOQUdFUiA9IGdsLnN0b3JhZ2UuSW5tZW1NYW5hZ2VyKCkKQ09ERV9TTE9UID0gKAoJX0NBTENfTUFOQUdFUi5nZXRfc3RvcmVfc2xvdChnbC5zdG9yYWdlLlJPT1RfU0xPVF9JRCkKCS5pbmRpcmVjdChnbC52bS5BQkkucm9vdF9vZmZzZXRzLkNPREUpCgkuaWQKKQpMT0NLRURfU0xPVCA9ICgKCV9DQUxDX01BTkFHRVIuZ2V0X3N0b3JlX3Nsb3QoZ2wuc3RvcmFnZS5ST09UX1NMT1RfSUQpCgkuaW5kaXJlY3QoZ2wudm0uQUJJLnJvb3Rfb2Zmc2V0cy5MT0NLRURfU0xPVFMpCgkuaWQKKQoKVkFDQU5UX1NMT1QgPSBfQ0FMQ19NQU5BR0VSLmdldF9zdG9yZV9zbG90KGdsLnN0b3JhZ2UuUk9PVF9TTE9UX0lEKS5pbmRpcmVjdCgKCWdsLnZtLkFCSS5yb290X29mZnNldHMuTUFKT1IKKQoKU1BFQ0lBTF9TTE9UUyA9IFtnbC5zdG9yYWdlLlJPT1RfU0xPVF9JRCwgQ09ERV9TTE9ULCBMT0NLRURfU0xPVF0KClNQRUNJQUxfU0xPVFNfVFdJTlMgPSB7CglzbHQ6IFZBQ0FOVF9TTE9ULmluZGlyZWN0KGkpLmlkIGZvciBpLCBzbHQgaW4gZW51bWVyYXRlKFNQRUNJQUxfU0xPVFMpCn0KCgpkZWYgZ2V0X3R3aW5fdmxhKHNsb3RfaWQ6IGJ5dGVzKSAtPiBnbC5zdG9yYWdlLlZMQVtnbC50eXBlcy51OF06CglyZXR1cm4gZ2wuc3RvcmFnZS5jYXN0X3Nsb3QoCgkJZ2wuc3RvcmFnZS5WTEFbZ2wudHlwZXMudThdLCBnbC5zdG9yYWdlLlJvb3QuTUFOQUdFUiwgc2xvdF9pZCwgMAoJKQoKCmRlZiB3cml0ZV90b190d2luKHNsb3RfaWQ6IGJ5dGVzLCBvZmZzZXQ6IGludCwgZGF0YTogYnl0ZXMpOgoJYXNfdmxhID0gZ2V0X3R3aW5fdmxhKHNsb3RfaWQpCglvbGRfbGVuID0gbGVuKGFzX3ZsYSkKCWFzX3ZsYS5zbG90KCkud3JpdGUoYXNfdmxhLmRhdGFfb2Zmc2V0KCkgKyBvZmZzZXQsIGRhdGEpCglhc192bGEuc2V0X2xlbmd0aChtYXgob2xkX2xlbiwgb2Zmc2V0ICsgbGVuKGRhdGEpKSkKCgpkZWYgcmVhZF9mcm9tX3R3aW4oc2xvdF9pZDogYnl0ZXMsIG9mZnNldDogaW50LCBsZW5ndGg6IGludCkgLT4gYnl0ZXM6CglzbG90ID0gZ2wuc3RvcmFnZS5Sb290Lk1BTkFHRVIuZ2V0X3N0b3JlX3Nsb3Qoc2xvdF9pZCkKCXJldHVybiBzbG90LnJlYWQob2Zmc2V0ICsgNCwgbGVuZ3RoKQoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmLCAqLCBzYXZlX2RlZmF1bHRfbG9ja2VkX3Nsb3RzOiBib29sID0gVHJ1ZSk6CgkJcm9vdCA9IGdsLnN0b3JhZ2UuUm9vdC5nZXQoKQoKCQlpZiBzYXZlX2RlZmF1bHRfbG9ja2VkX3Nsb3RzOgoJCQl0d2luX3Nsb3RfaWQgPSBTUEVDSUFMX1NMT1RTX1RXSU5TW0xPQ0tFRF9TTE9UXQoJCQlsb2NrZWRfc2xvdHNfZHN0ID0gZ2wuc3RvcmFnZS5jYXN0X3Nsb3QoCgkJCQlnbC5zdG9yYWdlLlZMQVtnbC50eXBlcy51MjU2XSwgZ2wuc3RvcmFnZS5Sb290Lk1BTkFHRVIsIHR3aW5fc2xvdF9pZCwgNAoJCQkpCgkJCWxvY2tlZF9zbG90c19kc3QuYXNzaWduKHJvb3QubG9ja2VkX3Nsb3RzLmdldCgpKQoKCQkJbG9ja2VkX3Nsb3RzX2RzdF92bGEgPSBnZXRfdHdpbl92bGEodHdpbl9zbG90X2lkKQoJCQlsb2NrZWRfc2xvdHNfZHN0X3ZsYS5zZXRfbGVuZ3RoKAoJCQkJbGVuKGxvY2tlZF9zbG90c19kc3QpICogMzIgKyBsb2NrZWRfc2xvdHNfZHN0LmRhdGFfb2Zmc2V0KCkKCQkJKQoKCQlyb290LmxvY2tlZF9zbG90cy5nZXQoKS50cnVuY2F0ZSgpCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIHdyaXRlKHNlbGYsIGRhdGE6IGxpc3RbdHlwaW5nLkFueV0pOgoJCSIiIgoJCVdyaXRlIGRhdGEgdG8gdGhlIGNvbnRyYWN0LgoKCQk6cGFyYW0gZGF0YTogbGlzdCBvZiBkYXRhIGl0ZW1zIHRvIHdyaXRlIGluIGZvcm1hdCBgYChzbG90OiBieXRlWzMyXSwgb2Zmc2V0OiB1MzIsIGRhdGE6IGJ5dGVzKWBgCgkJIiIiCgoJCWZvciBzbG90LCBvZmZzZXQsIHNsaWNlIGluIGRhdGE6CgkJCWlmIHNsb3QgaW4gU1BFQ0lBTF9TTE9UU19UV0lOUy52YWx1ZXMoKToKCQkJCWdsLnZtLlVzZXJFcnJvci5pbW1lZGlhdGUoJ0Nhbm5vdCB3cml0ZSB0byB0aGUgdGVtcG9yYXJ5IGNvZGUgc2xvdHMnKQoJCQlpZiB0d2luIDo9IFNQRUNJQUxfU0xPVFNfVFdJTlMuZ2V0KHNsb3QpOgoJCQkJd3JpdGVfdG9fdHdpbih0d2luLCBvZmZzZXQsIHNsaWNlKQoJCQllbHNlOgoJCQkJZ2wuc3RvcmFnZS5Sb290Lk1BTkFHRVIuZ2V0X3N0b3JlX3Nsb3Qoc2xvdCkud3JpdGUob2Zmc2V0LCBzbGljZSkKCglAZ2wucHVibGljLndyaXRlCglkZWYgcHVzaF9jb2RlKHNlbGYsIGNvZGU6IGJ5dGVzKToKCQkiIiIKCQlQdXNoIGNvZGUgdG8gdGhlIGNvbnRyYWN0LiBUaGlzIHdpbGwgd3JpdGUgdGhlIGNvZGUgdG8gYSB0ZW1wb3Jhcnkgc2xvdCwgd2hpY2ggY2FuIGJlIGNvcGllZCB0byB0aGUgY29kZSBzbG90IGluIHRoZSBgYGZpbmlzaGBgIG1ldGhvZC4KCgkJOnBhcmFtIGNvZGU6IGNvZGUgdG8gcHVzaAoKCQkuLiB3YXJuaW5nOjoKCQkJRXhhY3RseSBvbmUgb2YgYGB3cml0ZWBgIG9yIGBgcHVzaF9jb2RlYGAgbXVzdCBiZSBjYWxsZWQgZm9yIGNvZGUgaW5pdGlhbGl6YXRpb24sCgkJCW90aGVyd2lzZSB0aGUgY29udHJhY3QgbWF5IGJlIGxlZnQgaW4gdW5kZWZpbmVkIHN0YXRlCgkJIiIiCgoJCXR3aW5fc2xvdF9pZCA9IFNQRUNJQUxfU0xPVFNfVFdJTlNbQ09ERV9TTE9UXQoJCWNvZGVfdHdpbl92bGEgPSBnZXRfdHdpbl92bGEodHdpbl9zbG90X2lkKQoJCWNvZGVfdmxhID0gZ2wuc3RvcmFnZS5jYXN0X3Nsb3QoCgkJCWdsLnN0b3JhZ2UuVkxBW2dsLnR5cGVzLnU4XSwgZ2wuc3RvcmFnZS5Sb290Lk1BTkFHRVIsIHR3aW5fc2xvdF9pZCwgNAoJCSkKCQljb2RlX3ZsYS5leHRlbmQoY29kZSkKCQluZXdfbGVuID0gbGVuKGNvZGVfdmxhKQoJCWNvZGVfdHdpbl92bGEuc2V0X2xlbmd0aChuZXdfbGVuICsgNCkKCglAZ2wucHVibGljLndyaXRlCglkZWYgZmluaXNoKHNlbGYpOgoJCSIiIgoJCUZpbmlzaCBib290c3RyYXBwaW5nLiBUaGlzIHdpbGwgY29weSB0aGUgY29kZSBmcm9tIHRoZSB0ZW1wb3Jhcnkgc2xvdCB0byB0aGUgY29kZSBzbG90IGFuZCBtYWtlIGl0IGF2YWlsYWJsZSBmb3IgZXhlY3V0aW9uLgoJCSIiIgoJCUJVRl9TSVpFID0gNjU1MzYKCQlmb3IgZHN0LCBzcmMgaW4gU1BFQ0lBTF9TTE9UU19UV0lOUy5pdGVtcygpOgoJCQl2bGFfZnJvbSA9IGdldF90d2luX3ZsYShzcmMpCgkJCWNvcHlfbGVuID0gbGVuKHZsYV9mcm9tKQoJCQl0byA9IGdsLnN0b3JhZ2UuUm9vdC5NQU5BR0VSLmdldF9zdG9yZV9zbG90KGRzdCkKCQkJZm9yIG9mZnNldCBpbiByYW5nZSgwLCBjb3B5X2xlbiwgQlVGX1NJWkUpOgoJCQkJY2h1bmtfc2l6ZSA9IG1pbihCVUZfU0laRSwgY29weV9sZW4gLSBvZmZzZXQpCgkJCQlkYXRhID0gdmxhX2Zyb20uc2xvdCgpLnJlYWQodmxhX2Zyb20uZGF0YV9vZmZzZXQoKSArIG9mZnNldCwgY2h1bmtfc2l6ZSkKCQkJCXRvLndyaXRlKG9mZnNldCwgZGF0YSkKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/storage/bootstrapper.0_0.hash b/tests/cases/stable/storage/bootstrapper.0_0.hash deleted file mode 100644 index 0f52d8aa1..000000000 --- a/tests/cases/stable/storage/bootstrapper.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAA0VowI3LUbDran4l8dNNJu/4ORQx5gWfJ9YD42vhd71fpbD6gAAAACDAioAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/storage/bootstrapper.0_0_0.hash b/tests/cases/stable/storage/bootstrapper.0_0_0.hash deleted file mode 100644 index c1d32f4a7..000000000 --- a/tests/cases/stable/storage/bootstrapper.0_0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAA0VowISZlOrevjVPFLYyIb5z3rEcM06Rjp/RVrY1uIgENBFrQAAAACDCGsAAABnAAAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCgoKY2xhc3MgQ29udHJhYwAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/storage/bootstrapper.0_0_0_0.hash b/tests/cases/stable/storage/bootstrapper.0_0_0_0.hash deleted file mode 100644 index 1060f1873..000000000 --- a/tests/cases/stable/storage/bootstrapper.0_0_0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowISZlOrevjVPFLYyIb5z3rEcM06Rjp/RVrY1uIgENBFrQAAAACDAtIAAADOAAAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxhFaMCEmZTq3r41TxS2MiG+c96xHDNOkY6f0Va2NbiIBDQRa0AAAADgwgKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWZpZWxkOiBpMzIKCglAZ2wucHVibGljLndyaXRlCglkZWYgZ2V0X2ZpZWxkKHNlbGYpOgoJCXByaW50KGludChzZWxmLmZpZWxkKSkKAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/storage/bootstrapper.0_0_0_0_0.hash b/tests/cases/stable/storage/bootstrapper.0_0_0_0_0.hash deleted file mode 100644 index b3d9e6578..000000000 --- a/tests/cases/stable/storage/bootstrapper.0_0_0_0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDDs4AAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglmaWVsZDogaTMyCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGdldF9maWVsZChzZWxmKToKCQlwcmludChpbnQoc2VsZi5maWVsZCkpCi5yb290X29mZnNldHMuBQ== diff --git a/tests/cases/stable/storage/bootstrapper.0_0_0_0_0_0.hash b/tests/cases/stable/storage/bootstrapper.0_0_0_0_0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/storage/bootstrapper.0_0_0_0_0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/storage/bootstrapper.jsonnet b/tests/cases/stable/storage/bootstrapper.jsonnet index b29d0df6a..462e8fbeb 100644 --- a/tests/cases/stable/storage/bootstrapper.jsonnet +++ b/tests/cases/stable/storage/bootstrapper.jsonnet @@ -3,8 +3,8 @@ local s = simple.run('${jsonnetDir}/${fileBaseName}.py'); local util = import 'templates/util.jsonnet'; local target_code = importstr './bootstrapper_target.py'; -// contract instance slot = sha3_256(ROOT_SLOT_ID(32 zero bytes) + CONTRACT_OFFSET(0 as u32 le)) -local contract_instance_slot = '372d46c3ada9f897c74d349bbfe0e450c798167c9f580f8daf85def57e96c3ea'; +// contract instance slot = sha3_256(ROOT_SLOT_ID(32 zero bytes) + CONTRACT_OFFSET(1 as u32 le)) +local contract_instance_slot = 'e1ae23412792df6b6a98fb7c9839701fb8b02b6fc7ed022810f78346494685e7'; {entry: util.addPaths([util.chain([ // deploy bootstrapper diff --git a/tests/cases/stable/storage/floats.0.hash b/tests/cases/stable/storage/floats.0.hash deleted file mode 100644 index 44a483c37..000000000 --- a/tests/cases/stable/storage/floats.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDFlIBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKZnJvbSBnZW5sYXllci5zdG9yYWdlLl9pbnRlcm5hbC5nZW5lcmF0ZSBpbXBvcnQgZ2VuZXJhdGVfc3RvcmFnZQoKCkBnZW5lcmF0ZV9zdG9yYWdlCmNsYXNzIFRlc3Q6Cglmb286IGZsb2F0CgoJZGVmIGFiYyhzZWxmKToKCQlyZXR1cm4gc2VsZi5mb28KCgp0c3QgPSBUZXN0KCkKdHN0LmZvbyA9IDAuNQoKYXNzZXJ0IHRzdC5mb28gPT0gMC41CmFzc2VydCB0eXBlKHRzdC5mb28pIGlzIGZsb2F0CnByaW50KHRzdC5mb28pCgpleGl0KDApCgAAAAAAAAAAAAAF diff --git a/tests/cases/stable/storage/gvm-89.0.hash b/tests/cases/stable/storage/gvm-89.0.hash deleted file mode 100644 index 19f03de3a..000000000 --- a/tests/cases/stable/storage/gvm-89.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDGGkBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKZnJvbSBkYXRhY2xhc3NlcyBpbXBvcnQgZGF0YWNsYXNzCmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCmZyb20gZ2VubGF5ZXIuc3RvcmFnZSBpbXBvcnQgYWxsb3cKCgpAYWxsb3cKQGRhdGFjbGFzcwpjbGFzcyBGb286Cgl4OiBnbC5EeW5BcnJheVtzdHJdCgoKY2xhc3MgTWFpbihnbC5jb250cmFjdC5Db250cmFjdCk6CglmOiBnbC5EeW5BcnJheVtGb29dCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG1haW4oc2VsZik6CgkJc2VsZi5mLmFwcGVuZChGb28oWycxMjMnXSkpCgkJcmV0dXJuIFtpIGZvciBpIGluIHNlbGYuZl0KAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/storage/gvm-89.0_0.hash b/tests/cases/stable/storage/gvm-89.0_0.hash deleted file mode 100644 index d5d0380d0..000000000 --- a/tests/cases/stable/storage/gvm-89.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQENDgF4DRwxMjMAJRWjAjctRsOtqfiXx000m7/g5FDHmBZ8n1gPja+F3vV+lsPqAAAAAIMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowK/3qmf3S8yrjpIVx1Q6ejcB/QQx6foIUwOn3NSI01TlgAAAACDAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMC1SZia+5PJP/Ww2xfjSWh6XcvGQxNaICn3bVyWZcl6e8AAAAAgwIxMjMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAupw/Ct4Am+EqQsq6IN2azBvld5Bwi2wvgVbdF1rlfQfAAAAAIMCAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/storage/locking/default-frozen.0.hash b/tests/cases/stable/storage/locking/default-frozen.0.hash deleted file mode 100644 index 929dd1528..000000000 --- a/tests/cases/stable/storage/locking/default-frozen.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDOHEDAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCm5ld19jb2RlID0gYiIiIlwKIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KcHJpbnQoIlBhdGNoZWQhIikKZXhpdCgzMCkKIiIiCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJZGVmIF9faW5pdF9fKHNlbGYsIG1vZGlmaWVyczogbGlzdFtBZGRyZXNzXSwgbW9kaWZ5X2luX2N0b3I6IGJvb2wpOgoJCXJvb3QgPSBnbC5zdG9yYWdlLlJvb3QuZ2V0KCkKCQlyb290LnVwZ3JhZGVycy5nZXQoKS5leHRlbmQobW9kaWZpZXJzKQoKCQlzZWxmLnNob3dfaW5mbygpCgoJCWlmIG1vZGlmeV9pbl9jdG9yOgoJCQlzZWxmLnRyeV9tb2RpZnkoKQoKCWRlZiBzaG93X2luZm8oc2VsZik6CgkJcm9vdCA9IGdsLnN0b3JhZ2UuUm9vdC5nZXQoKQoKCQlwcmludChsaXN0KHJvb3QubG9ja2VkX3Nsb3RzLmdldCgpKSkKCQlwcmludChsaXN0KHJvb3QudXBncmFkZXJzLmdldCgpKSkKCglAZ2wucHVibGljLndyaXRlCglkZWYgbm9wKHNlbGYpOgoJCXBhc3MKCglAZ2wucHVibGljLndyaXRlCglkZWYgdHJ5X21vZGlmeShzZWxmKToKCQlyb290ID0gZ2wuc3RvcmFnZS5Sb290LmdldCgpCgoJCXNlbGYuc2hvd19pbmZvKCkKCgkJY29kZSA9IHJvb3QuY29kZS5nZXQoKQoJCXRyeToKCQkJY29kZS50cnVuY2F0ZSgpICAjIDwtIHdlIHNob3VsZCBlbmNvdW50ZXIgZXJyb3IgaGVyZQoJCWV4Y2VwdCBCYXNlRXhjZXB0aW9uIGFzIGU6CgkJCXByaW50KGUpCgkJZWxzZToKCQkJY29kZS5hc3NpZ24obmV3X2NvZGUpCgkJcHJpbnQobGVuKGNvZGUpID09IGxlbihuZXdfY29kZSkpCgAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/storage/locking/default-frozen.0.stdout b/tests/cases/stable/storage/locking/default-frozen.0.stdout index 23fb2da8d..502c0e297 100644 --- a/tests/cases/stable/storage/locking/default-frozen.0.stdout +++ b/tests/cases/stable/storage/locking/default-frozen.0.stdout @@ -1,3 +1,3 @@ -[0, 104719743780096590577697194990451901900258198514698274453690604555695722573537, 5147135863452175656394978567785114489906633378855095627257376406960105455802, 46342954650747611132690097513405510122375903838997656252402239048600340445473] +[0, 5147135863452175656394978567785114489906633378855095627257376406960105455802, 46342954650747611132690097513405510122375903838997656252402239048600340445473, 97210530485491999172923574369323190562438421669572628099136573576019724640551] [] executed with `Return(null)` diff --git a/tests/cases/stable/storage/locking/default-frozen.0_0.hash b/tests/cases/stable/storage/locking/default-frozen.0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/storage/locking/default-frozen.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/storage/locking/default-frozen.0_0.stdout b/tests/cases/stable/storage/locking/default-frozen.0_0.stdout index 0e5d32afc..778890e66 100644 --- a/tests/cases/stable/storage/locking/default-frozen.0_0.stdout +++ b/tests/cases/stable/storage/locking/default-frozen.0_0.stdout @@ -1,4 +1,4 @@ -[0, 104719743780096590577697194990451901900258198514698274453690604555695722573537, 5147135863452175656394978567785114489906633378855095627257376406960105455802, 46342954650747611132690097513405510122375903838997656252402239048600340445473] +[0, 5147135863452175656394978567785114489906633378855095627257376406960105455802, 46342954650747611132690097513405510122375903838997656252402239048600340445473, 97210530485491999172923574369323190562438421669572628099136573576019724640551] [] 6: forbidden False diff --git a/tests/cases/stable/storage/locking/default-frozen.0_0_0.hash b/tests/cases/stable/storage/locking/default-frozen.0_0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/storage/locking/default-frozen.0_0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/storage/locking/modify_ctor.0.hash b/tests/cases/stable/storage/locking/modify_ctor.0.hash deleted file mode 100644 index 917dadfd4..000000000 --- a/tests/cases/stable/storage/locking/modify_ctor.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDOD8AAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQpwcmludCgiUGF0Y2hlZCEiKQpleGl0KDMwKQogZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCm5ld19jb2RlID0gYiIiIlwKIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KcHJpbnQoIlBhdGNoZWQhIikKZXhpdCgzMCkKIiIiCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJZGVmIF9faW5pdF9fKHNlbGYsIG1vZGlmaWVyczogbGlzdFtBZGRyZXNzXSwgbW9kaWZ5X2luX2N0b3I6IGJvb2wpOgoJCXJvb3QgPSBnbC5zdG9yYWdlLlJvb3QuZ2V0KCkKCQlyb290LnVwZ3JhZGVycy5nZXQoKS5leHRlbmQobW9kaWZpZXJzKQoKCQlzZWxmLnNob3dfaW5mbygpCgoJCWlmIG1vZGlmeV9pbl9jdG9yOgoJCQlzZWxmLnRyeV9tb2RpZnkoKQoKCWRlZiBzaG93X2luZm8oc2VsZik6CgkJcm9vdCA9IGdsLnN0b3JhZ2UuUm9vdC5nZXQoKQoKCQlwcmludChsaXN0KHJvb3QubG9ja2VkX3Nsb3RzLmdldCgpKSkKCQlwcmludChsaXN0KHJvb3QudXBncmFkZXJzLmdldCgpKSkKCglAZ2wucHVibGljLndyaXRlCglkZWYgbm9wKHNlbGYpOgoJCXBhc3MKCglAZ2wucHVibGljLndyaXRlCglkZWYgdHJ5X21vZGlmeShzZWxmKToKCQlyb290ID0gZ2wuc3RvcmFnZS5Sb290LmdldCgpCgoJCXNlbGYuc2hvd19pbmZvKCkKCgkJY29kZSA9IHJvb3QuY29kZS5nZXQoKQoJCXRyeToKCQkJY29kZS50cnVuY2F0ZSgpICAjIDwtIHdlIHNob3VsZCBlbmNvdW50ZXIgZXJyb3IgaGVyZQoJCWV4Y2VwdCBCYXNlRXhjZXB0aW9uIGFzIGU6CgkJCXByaW50KGUpCgkJZWxzZToKCQkJY29kZS5hc3NpZ24obmV3X2NvZGUpCgkJcHJpbnQobGVuKGNvZGUpID09IGxlbihuZXdfY29kZSkpCgAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/storage/locking/modify_ctor.0.stdout b/tests/cases/stable/storage/locking/modify_ctor.0.stdout index dc59f8508..304283b16 100644 --- a/tests/cases/stable/storage/locking/modify_ctor.0.stdout +++ b/tests/cases/stable/storage/locking/modify_ctor.0.stdout @@ -1,6 +1,6 @@ -[0, 104719743780096590577697194990451901900258198514698274453690604555695722573537, 5147135863452175656394978567785114489906633378855095627257376406960105455802, 46342954650747611132690097513405510122375903838997656252402239048600340445473] +[0, 5147135863452175656394978567785114489906633378855095627257376406960105455802, 46342954650747611132690097513405510122375903838997656252402239048600340445473, 97210530485491999172923574369323190562438421669572628099136573576019724640551] [] -[0, 104719743780096590577697194990451901900258198514698274453690604555695722573537, 5147135863452175656394978567785114489906633378855095627257376406960105455802, 46342954650747611132690097513405510122375903838997656252402239048600340445473] +[0, 5147135863452175656394978567785114489906633378855095627257376406960105455802, 46342954650747611132690097513405510122375903838997656252402239048600340445473, 97210530485491999172923574369323190562438421669572628099136573576019724640551] [] True executed with `Return(null)` diff --git a/tests/cases/stable/storage/locking/modify_ctor.0_0.hash b/tests/cases/stable/storage/locking/modify_ctor.0_0.hash deleted file mode 100644 index 5316a6984..000000000 --- a/tests/cases/stable/storage/locking/modify_ctor.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LRFkZXhpdF9jb2RlIDMwAAUF diff --git a/tests/cases/stable/storage/locking/modify_later.0.hash b/tests/cases/stable/storage/locking/modify_later.0.hash deleted file mode 100644 index 27505c4e8..000000000 --- a/tests/cases/stable/storage/locking/modify_later.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAB0VowIhueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAACDAgEAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF57oAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMC4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhecAAAAAgzhxAwAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCgpuZXdfY29kZSA9IGIiIiJcCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CnByaW50KCJQYXRjaGVkISIpCmV4aXQoMzApCiIiIgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmLCBtb2RpZmllcnM6IGxpc3RbQWRkcmVzc10sIG1vZGlmeV9pbl9jdG9yOiBib29sKToKCQlyb290ID0gZ2wuc3RvcmFnZS5Sb290LmdldCgpCgkJcm9vdC51cGdyYWRlcnMuZ2V0KCkuZXh0ZW5kKG1vZGlmaWVycykKCgkJc2VsZi5zaG93X2luZm8oKQoKCQlpZiBtb2RpZnlfaW5fY3RvcjoKCQkJc2VsZi50cnlfbW9kaWZ5KCkKCglkZWYgc2hvd19pbmZvKHNlbGYpOgoJCXJvb3QgPSBnbC5zdG9yYWdlLlJvb3QuZ2V0KCkKCgkJcHJpbnQobGlzdChyb290LmxvY2tlZF9zbG90cy5nZXQoKSkpCgkJcHJpbnQobGlzdChyb290LnVwZ3JhZGVycy5nZXQoKSkpCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG5vcChzZWxmKToKCQlwYXNzCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIHRyeV9tb2RpZnkoc2VsZik6CgkJcm9vdCA9IGdsLnN0b3JhZ2UuUm9vdC5nZXQoKQoKCQlzZWxmLnNob3dfaW5mbygpCgoJCWNvZGUgPSByb290LmNvZGUuZ2V0KCkKCQl0cnk6CgkJCWNvZGUudHJ1bmNhdGUoKSAgIyA8LSB3ZSBzaG91bGQgZW5jb3VudGVyIGVycm9yIGhlcmUKCQlleGNlcHQgQmFzZUV4Y2VwdGlvbiBhcyBlOgoJCQlwcmludChlKQoJCWVsc2U6CgkJCWNvZGUuYXNzaWduKG5ld19jb2RlKQoJCXByaW50KGxlbihjb2RlKSA9PSBsZW4obmV3X2NvZGUpKQoAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/storage/locking/modify_later.0.stdout b/tests/cases/stable/storage/locking/modify_later.0.stdout index 444226f68..392f2467f 100644 --- a/tests/cases/stable/storage/locking/modify_later.0.stdout +++ b/tests/cases/stable/storage/locking/modify_later.0.stdout @@ -1,3 +1,3 @@ -[0, 104719743780096590577697194990451901900258198514698274453690604555695722573537, 5147135863452175656394978567785114489906633378855095627257376406960105455802, 46342954650747611132690097513405510122375903838997656252402239048600340445473] +[0, 5147135863452175656394978567785114489906633378855095627257376406960105455802, 46342954650747611132690097513405510122375903838997656252402239048600340445473, 97210530485491999172923574369323190562438421669572628099136573576019724640551] [Address("0x0200000000000000000000000000000000000000")] executed with `Return(null)` diff --git a/tests/cases/stable/storage/locking/modify_later.0_0.hash b/tests/cases/stable/storage/locking/modify_later.0_0.hash deleted file mode 100644 index bc4ae18db..000000000 --- a/tests/cases/stable/storage/locking/modify_later.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDBj8AAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQpwcmludCgiUGF0Y2hlZCEiKQpleGl0KDMwKQogZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCm5ldwU= diff --git a/tests/cases/stable/storage/locking/modify_later.0_0.stdout b/tests/cases/stable/storage/locking/modify_later.0_0.stdout index 72d3cd2e4..e93931964 100644 --- a/tests/cases/stable/storage/locking/modify_later.0_0.stdout +++ b/tests/cases/stable/storage/locking/modify_later.0_0.stdout @@ -1,4 +1,4 @@ -[0, 104719743780096590577697194990451901900258198514698274453690604555695722573537, 5147135863452175656394978567785114489906633378855095627257376406960105455802, 46342954650747611132690097513405510122375903838997656252402239048600340445473] +[0, 5147135863452175656394978567785114489906633378855095627257376406960105455802, 46342954650747611132690097513405510122375903838997656252402239048600340445473, 97210530485491999172923574369323190562438421669572628099136573576019724640551] [Address("0x0200000000000000000000000000000000000000")] True executed with `Return(null)` diff --git a/tests/cases/stable/storage/locking/modify_later.0_0_0.hash b/tests/cases/stable/storage/locking/modify_later.0_0_0.hash deleted file mode 100644 index 5316a6984..000000000 --- a/tests/cases/stable/storage/locking/modify_later.0_0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LRFkZXhpdF9jb2RlIDMwAAUF diff --git a/tests/cases/stable/storage/np.0.hash b/tests/cases/stable/storage/np.0.hash deleted file mode 100644 index c97a162ee..000000000 --- a/tests/cases/stable/storage/np.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDHJ8BAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKaW1wb3J0IG51bXB5IGFzIG5wCgppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKZnJvbSBnZW5sYXllci5zdG9yYWdlLl9pbnRlcm5hbC5nZW5lcmF0ZSBpbXBvcnQgZ2VuZXJhdGVfc3RvcmFnZQoKCkBnZW5lcmF0ZV9zdG9yYWdlCmNsYXNzIFRlc3Q6Cglmb286IG5wLmZsb2F0MzIKCglkZWYgYWJjKHNlbGYpOgoJCXJldHVybiBzZWxmLmZvbwoKCnRzdCA9IFRlc3QoKQp0c3QuZm9vID0gbnAuZmxvYXQzMigwLjUpCgphc3NlcnQgdHN0LmZvbyA9PSAwLjUsIGYne3RzdC5mb299Jwphc3NlcnQgdHlwZSh0c3QuZm9vKSBpcyBucC5mbG9hdDMyLCBmJ3t0eXBlKHRzdC5mb28pfScKcHJpbnQodHN0LmZvbykKCmV4aXQoMCkKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/storage/persists.0.hash b/tests/cases/stable/storage/persists.0.hash deleted file mode 100644 index adc75de2d..000000000 --- a/tests/cases/stable/storage/persists.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAADUVowIhoYw7XQjALrPQfBJfrJU3xQPXxybmmGkvhq9v6upRRgAAAACDBAEAAAAMAAAAAAAAAAIAAAABAwAAAB4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowI3LUbDran4l8dNNJu/4ORQx5gWfJ9YD42vhd71fpbD6gAAAACDAgEAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCW4piZJ58jouEzsFEVfPYnJ9uo5sOKOWfMo2iXltpKcgAAAAAgwJhYmMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAroAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELAAAAAIMKBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhee6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjArtHW19KeR3j/qGkKz3kHNgU+bllSDToaqVyrtJw9Q7jAAAAAIMCMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDFj4BAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CgltOiBnbC5UcmVlTWFwW3N0ciwgdTMyXQoKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwcmludCgnZmlyc3QnKQoJCXNlbGYubVsnMSddID0gMTIKCQlzZWxmLm1bJ2FiYyddID0gMzAKCglAZ2wucHVibGljLndyaXRlCglkZWYgc2Vjb25kKHNlbGYpOgoJCXByaW50KCdzZWNvbmQnKQoJCXByaW50KGxpc3Qoc2VsZi5tLml0ZW1zKCkpKQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/storage/persists.0_0.hash b/tests/cases/stable/storage/persists.0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/stable/storage/persists.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/stable/storage/read_nondet.0.hash b/tests/cases/stable/storage/read_nondet.0.hash deleted file mode 100644 index 34d616dc8..000000000 --- a/tests/cases/stable/storage/read_nondet.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAACUVowI3LUbDran4l8dNNJu/4ORQx5gWfJ9YD42vhd71fpbD6gAAAACDAgMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF57oAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCv96pn90vMq46SFcdUOno3Af0EMen6CFMDp9zUiNNU5YAAAAAgwI0NTYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAuGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnAAAAAIMUHQEAACMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjpsYXRlc3QiIH0KCmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCgoKY2xhc3MgU3RvcmFnZShnbC5jb250cmFjdC5Db250cmFjdCk6CglhOiBzdHIKCglkZWYgX19pbml0X18oc2VsZik6CgkJc2VsZi5hID0gJzEyMycKCgkJZGVmIGYoKToKCQkJcHJpbnQoc2VsZi5hKQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGYpCgkJc2VsZi5hID0gJzQ1NicKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGYpCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/storage/storage_tree_map.0.hash b/tests/cases/stable/storage/storage_tree_map.0.hash deleted file mode 100644 index 94947fa18..000000000 --- a/tests/cases/stable/storage/storage_tree_map.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDFkgBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKZnJvbSBnZW5sYXllci5zdG9yYWdlLl9pbnRlcm5hbC5nZW5lcmF0ZSBpbXBvcnQgZ2VuZXJhdGVfc3RvcmFnZQoKCkBnZW5lcmF0ZV9zdG9yYWdlCmNsYXNzIFVzZXJTdG9yYWdlOgoJbTogZ2wuVHJlZU1hcFtzdHIsIHUzMl0KCgp0c3QgPSBVc2VyU3RvcmFnZSgpCgp0c3QubVsnMSddID0gMTIKdHN0Lm1bJzInXSA9IDEzCmRlbCB0c3QubVsnMSddCnByaW50KCcxJyBpbiB0c3QubSwgdHN0Lm1bJzInXSkKCmV4aXQoMCkKAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/storage/to_str.0.hash b/tests/cases/stable/storage/to_str.0.hash deleted file mode 100644 index 8d7a3e77b..000000000 --- a/tests/cases/stable/storage/to_str.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDFloBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKZnJvbSBnZW5sYXllci5zdG9yYWdlIGltcG9ydCBhbGxvdwoKZnJvbSBkYXRhY2xhc3NlcyBpbXBvcnQgZGF0YWNsYXNzCmltcG9ydCBkYXRldGltZQoKCkBhbGxvdwpAZGF0YWNsYXNzCmNsYXNzIFVzZXI6CgluYW1lOiBzdHIKCWJpcnRoZGF5OiBkYXRldGltZS5kYXRldGltZQoKCmNsYXNzIExsbUVyYzIwKGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCXg6IFVzZXIKCglkZWYgX19pbml0X18oc2VsZikgLT4gTm9uZToKCQlwcmludChzdHIoc2VsZi54KSkKAAAF diff --git a/tests/cases/stable/storage/tree_map_nested.0.hash b/tests/cases/stable/storage/tree_map_nested.0.hash deleted file mode 100644 index f85f77c82..000000000 --- a/tests/cases/stable/storage/tree_map_nested.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAC0VowIhoYw7XQjALrPQfBJfrJU3xQPXxybmmGkvhq9v6upRRgAAAACDBAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowI3LUbDran4l8dNNJu/4ORQx5gWfJ9YD42vhd71fpbD6gAAAACDAgEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCUkaslAbRP9iFuRi0yOEVYFjB69iTYYmy7yi8YAvi5+YAAAAAgwQBAQEBAQEBAQEBAQEBAQEBAQEBAQ0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF57oAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMC4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhecAAAAAgx7MAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJc3Q6IGdsLlRyZWVNYXBbQWRkcmVzcywgZ2wuVHJlZU1hcFtBZGRyZXNzLCB1MjU2XV0KCglkZWYgX19pbml0X18oc2VsZik6CgkJZmlyc3QgPSBzZWxmLnN0LmdldF9vcl9pbnNlcnRfZGVmYXVsdChBZGRyZXNzKGInXHgwMCcgKiAyMCkpCgkJcHJpbnQoe2suYXNfaGV4OiBkaWN0KHYuaXRlbXMoKSkgZm9yIGssIHYgaW4gc2VsZi5zdC5pdGVtcygpfSkKCQlwcmludChkaWN0KGZpcnN0Lml0ZW1zKCkpKQoJCWZpcnN0W0FkZHJlc3MoYidceDAxJyAqIDIwKV0gPSAxMwoJCXByaW50KHtrLmFzX2hleDogZGljdCh2Lml0ZW1zKCkpIGZvciBrLCB2IGluIHNlbGYuc3QuaXRlbXMoKX0pCgAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/unstable/nondet/eq/ncomp/eq_prompt_non_comparative_validator.0.hash b/tests/cases/unstable/nondet/eq/ncomp/eq_prompt_non_comparative_validator.0.hash deleted file mode 100644 index d5e09be16..000000000 --- a/tests/cases/unstable/nondet/eq/ncomp/eq_prompt_non_comparative_validator.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDLtsCAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgppbXBvcnQgc3lzCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJZGVmIF9faW5pdF9fKHNlbGYpOgoJCWRlZiBnZXRfaW5wdXQoKToKCQkJcmV0dXJuICJBcyBwZXRzLCByYXRzIGFyZSBhZmZlY3Rpb25hdGUsIHBsYXlmdWwsIGFuZCBmb3JtIHN0cm9uZyBib25kcyB3aXRoIHRoZWlyIGh1bWFuIGNvbXBhbmlvbnMuIFRoZXkncmUgY3VyaW91cywgZW5qb3kgaW50ZXJhY3RpdmUgdG95cywgYW5kIGNhbiBsZWFybiB0cmlja3MgbXVjaCBsaWtlIHNtYWxsIGRvZ3MuIFRoZWlyIGFkYXB0YWJpbGl0eSwgaW50ZWxsaWdlbmNlLCBhbmQgY2hhcm1pbmcgcGVyc29uYWxpdGllcyBtYWtlIHRoZW0gdHJ1bHkgY29vbCBhbmltYWxzIHRoYXQgZGVzZXJ2ZSBtdWNoIG1vcmUgYXBwcmVjaWF0aW9uIHRoYW4gdGhleSBjdXJyZW50bHkgZ2V0LiIKCgkJcHJpbnQoCgkJCWdsLmVxX3ByaW5jaXBsZS5wcm9tcHRfbm9uX2NvbXBhcmF0aXZlKAoJCQkJZ2V0X2lucHV0LAoJCQkJdGFzaz0nUHJvZHVjZSBhIHRleHQgc3VtbWFyeScsCgkJCQljcml0ZXJpYT0nSXQgbXVzdCBiZSBzaG9ydGVyIHRoYW4gdGhlIG9yaWdpbmFsIHRleHQgYW5kIGJlIGEgdmFsaWQgc3VtbWFyeScsCgkJCSksCgkJCWZpbGU9c3lzLnN0ZGVyciwKCQkpCgAF diff --git a/tests/cases/unstable/nondet/eq/ncomp/eq_prompt_non_comparative_validator_bad.0.hash b/tests/cases/unstable/nondet/eq/ncomp/eq_prompt_non_comparative_validator_bad.0.hash deleted file mode 100644 index d5e09be16..000000000 --- a/tests/cases/unstable/nondet/eq/ncomp/eq_prompt_non_comparative_validator_bad.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDLtsCAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgppbXBvcnQgc3lzCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJZGVmIF9faW5pdF9fKHNlbGYpOgoJCWRlZiBnZXRfaW5wdXQoKToKCQkJcmV0dXJuICJBcyBwZXRzLCByYXRzIGFyZSBhZmZlY3Rpb25hdGUsIHBsYXlmdWwsIGFuZCBmb3JtIHN0cm9uZyBib25kcyB3aXRoIHRoZWlyIGh1bWFuIGNvbXBhbmlvbnMuIFRoZXkncmUgY3VyaW91cywgZW5qb3kgaW50ZXJhY3RpdmUgdG95cywgYW5kIGNhbiBsZWFybiB0cmlja3MgbXVjaCBsaWtlIHNtYWxsIGRvZ3MuIFRoZWlyIGFkYXB0YWJpbGl0eSwgaW50ZWxsaWdlbmNlLCBhbmQgY2hhcm1pbmcgcGVyc29uYWxpdGllcyBtYWtlIHRoZW0gdHJ1bHkgY29vbCBhbmltYWxzIHRoYXQgZGVzZXJ2ZSBtdWNoIG1vcmUgYXBwcmVjaWF0aW9uIHRoYW4gdGhleSBjdXJyZW50bHkgZ2V0LiIKCgkJcHJpbnQoCgkJCWdsLmVxX3ByaW5jaXBsZS5wcm9tcHRfbm9uX2NvbXBhcmF0aXZlKAoJCQkJZ2V0X2lucHV0LAoJCQkJdGFzaz0nUHJvZHVjZSBhIHRleHQgc3VtbWFyeScsCgkJCQljcml0ZXJpYT0nSXQgbXVzdCBiZSBzaG9ydGVyIHRoYW4gdGhlIG9yaWdpbmFsIHRleHQgYW5kIGJlIGEgdmFsaWQgc3VtbWFyeScsCgkJCSksCgkJCWZpbGU9c3lzLnN0ZGVyciwKCQkpCgAF diff --git a/tests/cases/unstable/nondet/validator/agree.0.hash b/tests/cases/unstable/nondet/validator/agree.0.hash deleted file mode 100644 index 9a6782d42..000000000 --- a/tests/cases/unstable/nondet/validator/agree.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDRlAEAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKaW1wb3J0IGh0bWwKZnJvbSBodG1sLnBhcnNlciBpbXBvcnQgSFRNTFBhcnNlcgoKZmNmID0gc2V0KFsnc2NyaXB0JywgJ2lmcmFtZSddKQoKCmNsYXNzIFNjcmlwdFJlbW92ZXIoSFRNTFBhcnNlcik6CglyZXN1bHQ6IGxpc3Rbc3RyXQoKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlzdXBlcigpLl9faW5pdF9fKCkKCQlzZWxmLnJlc3VsdCA9IFtdCgkJc2VsZi5pbl9zY3JpcHQgPSBGYWxzZQoKCWRlZiBoYW5kbGVfc3RhcnR0YWcoc2VsZiwgdGFnLCBhdHRycyk6CgkJaWYgdGFnLmxvd2VyKCkgaW4gZmNmOgoJCQlzZWxmLmluX3NjcmlwdCA9IFRydWUKCQllbGlmIG5vdCBzZWxmLmluX3NjcmlwdDoKCQkJc2VsZi5yZXN1bHQuYXBwZW5kKHNlbGYuZ2V0X3N0YXJ0dGFnX3RleHQoKSkKCglkZWYgaGFuZGxlX2VuZHRhZyhzZWxmLCB0YWcpOgoJCWlmIHRhZy5sb3dlcigpIGluIGZjZjoKCQkJc2VsZi5pbl9zY3JpcHQgPSBGYWxzZQoJCWVsaWYgbm90IHNlbGYuaW5fc2NyaXB0OgoJCQlzZWxmLnJlc3VsdC5hcHBlbmQoZic8L3t0YWd9PicpCgoJZGVmIGhhbmRsZV9kYXRhKHNlbGYsIGRhdGEpOgoJCWlmIG5vdCBzZWxmLmluX3NjcmlwdDoKCQkJc2VsZi5yZXN1bHQuYXBwZW5kKGRhdGEpCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG1haW4oc2VsZiwgbW9kZTogc3RyKToKCQlkZWYgcnVuKCkgLT4gc3RyOgoJCQlyZXMgPSBnbC5ub25kZXQud2ViLnJlbmRlcigKCQkJCSdodHRwczovL3Rlc3Qtc2VydmVyLmdlbmxheWVyLmNvbS9zdGF0aWMvZ2Vudm0vaGVsbG8uaHRtbCcsIG1vZGU9bW9kZQoJCQkpICAjIHR5cGU6IGlnbm9yZQoJCQlpZiBtb2RlID09ICdodG1sJzoKCQkJCXBhcnNlciA9IFNjcmlwdFJlbW92ZXIoKQoJCQkJcGFyc2VyLmZlZWQocmVzKQoJCQkJcmVzID0gJycuam9pbihwYXJzZXIucmVzdWx0KQoJCQlyZXR1cm4gcmVzCgoJCXByaW50KGdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEocnVuKS5zdHJpcCgpKQoAAAAAAAAAAAAAAAAF diff --git a/tests/cases/unstable/nondet/validator/agree.0_0.hash b/tests/cases/unstable/nondet/validator/agree.0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/unstable/nondet/validator/agree.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/unstable/nondet/validator/disagree.0.hash b/tests/cases/unstable/nondet/validator/disagree.0.hash deleted file mode 100644 index 9a6782d42..000000000 --- a/tests/cases/unstable/nondet/validator/disagree.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDRlAEAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKaW1wb3J0IGh0bWwKZnJvbSBodG1sLnBhcnNlciBpbXBvcnQgSFRNTFBhcnNlcgoKZmNmID0gc2V0KFsnc2NyaXB0JywgJ2lmcmFtZSddKQoKCmNsYXNzIFNjcmlwdFJlbW92ZXIoSFRNTFBhcnNlcik6CglyZXN1bHQ6IGxpc3Rbc3RyXQoKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlzdXBlcigpLl9faW5pdF9fKCkKCQlzZWxmLnJlc3VsdCA9IFtdCgkJc2VsZi5pbl9zY3JpcHQgPSBGYWxzZQoKCWRlZiBoYW5kbGVfc3RhcnR0YWcoc2VsZiwgdGFnLCBhdHRycyk6CgkJaWYgdGFnLmxvd2VyKCkgaW4gZmNmOgoJCQlzZWxmLmluX3NjcmlwdCA9IFRydWUKCQllbGlmIG5vdCBzZWxmLmluX3NjcmlwdDoKCQkJc2VsZi5yZXN1bHQuYXBwZW5kKHNlbGYuZ2V0X3N0YXJ0dGFnX3RleHQoKSkKCglkZWYgaGFuZGxlX2VuZHRhZyhzZWxmLCB0YWcpOgoJCWlmIHRhZy5sb3dlcigpIGluIGZjZjoKCQkJc2VsZi5pbl9zY3JpcHQgPSBGYWxzZQoJCWVsaWYgbm90IHNlbGYuaW5fc2NyaXB0OgoJCQlzZWxmLnJlc3VsdC5hcHBlbmQoZic8L3t0YWd9PicpCgoJZGVmIGhhbmRsZV9kYXRhKHNlbGYsIGRhdGEpOgoJCWlmIG5vdCBzZWxmLmluX3NjcmlwdDoKCQkJc2VsZi5yZXN1bHQuYXBwZW5kKGRhdGEpCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG1haW4oc2VsZiwgbW9kZTogc3RyKToKCQlkZWYgcnVuKCkgLT4gc3RyOgoJCQlyZXMgPSBnbC5ub25kZXQud2ViLnJlbmRlcigKCQkJCSdodHRwczovL3Rlc3Qtc2VydmVyLmdlbmxheWVyLmNvbS9zdGF0aWMvZ2Vudm0vaGVsbG8uaHRtbCcsIG1vZGU9bW9kZQoJCQkpICAjIHR5cGU6IGlnbm9yZQoJCQlpZiBtb2RlID09ICdodG1sJzoKCQkJCXBhcnNlciA9IFNjcmlwdFJlbW92ZXIoKQoJCQkJcGFyc2VyLmZlZWQocmVzKQoJCQkJcmVzID0gJycuam9pbihwYXJzZXIucmVzdWx0KQoJCQlyZXR1cm4gcmVzCgoJCXByaW50KGdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEocnVuKS5zdHJpcCgpKQoAAAAAAAAAAAAAAAAF diff --git a/tests/cases/unstable/nondet/validator/disagree.0_0.hash b/tests/cases/unstable/nondet/validator/disagree.0_0.hash deleted file mode 100644 index 9942c2585..000000000 --- a/tests/cases/unstable/nondet/validator/disagree.0_0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAAAUF diff --git a/tests/cases/unstable/nondet/web/get_webpage_html.0.hash b/tests/cases/unstable/nondet/web/get_webpage_html.0.hash deleted file mode 100644 index 9a6782d42..000000000 --- a/tests/cases/unstable/nondet/web/get_webpage_html.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDRlAEAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKaW1wb3J0IGh0bWwKZnJvbSBodG1sLnBhcnNlciBpbXBvcnQgSFRNTFBhcnNlcgoKZmNmID0gc2V0KFsnc2NyaXB0JywgJ2lmcmFtZSddKQoKCmNsYXNzIFNjcmlwdFJlbW92ZXIoSFRNTFBhcnNlcik6CglyZXN1bHQ6IGxpc3Rbc3RyXQoKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlzdXBlcigpLl9faW5pdF9fKCkKCQlzZWxmLnJlc3VsdCA9IFtdCgkJc2VsZi5pbl9zY3JpcHQgPSBGYWxzZQoKCWRlZiBoYW5kbGVfc3RhcnR0YWcoc2VsZiwgdGFnLCBhdHRycyk6CgkJaWYgdGFnLmxvd2VyKCkgaW4gZmNmOgoJCQlzZWxmLmluX3NjcmlwdCA9IFRydWUKCQllbGlmIG5vdCBzZWxmLmluX3NjcmlwdDoKCQkJc2VsZi5yZXN1bHQuYXBwZW5kKHNlbGYuZ2V0X3N0YXJ0dGFnX3RleHQoKSkKCglkZWYgaGFuZGxlX2VuZHRhZyhzZWxmLCB0YWcpOgoJCWlmIHRhZy5sb3dlcigpIGluIGZjZjoKCQkJc2VsZi5pbl9zY3JpcHQgPSBGYWxzZQoJCWVsaWYgbm90IHNlbGYuaW5fc2NyaXB0OgoJCQlzZWxmLnJlc3VsdC5hcHBlbmQoZic8L3t0YWd9PicpCgoJZGVmIGhhbmRsZV9kYXRhKHNlbGYsIGRhdGEpOgoJCWlmIG5vdCBzZWxmLmluX3NjcmlwdDoKCQkJc2VsZi5yZXN1bHQuYXBwZW5kKGRhdGEpCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG1haW4oc2VsZiwgbW9kZTogc3RyKToKCQlkZWYgcnVuKCkgLT4gc3RyOgoJCQlyZXMgPSBnbC5ub25kZXQud2ViLnJlbmRlcigKCQkJCSdodHRwczovL3Rlc3Qtc2VydmVyLmdlbmxheWVyLmNvbS9zdGF0aWMvZ2Vudm0vaGVsbG8uaHRtbCcsIG1vZGU9bW9kZQoJCQkpICAjIHR5cGU6IGlnbm9yZQoJCQlpZiBtb2RlID09ICdodG1sJzoKCQkJCXBhcnNlciA9IFNjcmlwdFJlbW92ZXIoKQoJCQkJcGFyc2VyLmZlZWQocmVzKQoJCQkJcmVzID0gJycuam9pbihwYXJzZXIucmVzdWx0KQoJCQlyZXR1cm4gcmVzCgoJCXByaW50KGdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEocnVuKS5zdHJpcCgpKQoAAAAAAAAAAAAAAAAF diff --git a/tests/cases/unstable/nondet/web/get_webpage_screenshot.0.hash b/tests/cases/unstable/nondet/web/get_webpage_screenshot.0.hash deleted file mode 100644 index 19976456e..000000000 --- a/tests/cases/unstable/nondet/web/get_webpage_screenshot.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDJksCAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKaW1wb3J0IHN5cwoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYsIG1vZGU6IHN0cik6CgkJZGVmIHJ1bigpOgoJCQlpbWcgPSBnbC5ub25kZXQud2ViLnJlbmRlcigKCQkJCSdodHRwczovL3Rlc3Qtc2VydmVyLmdlbmxheWVyLmNvbS9zdGF0aWMvZ2Vudm0vaGVsbG8uaHRtbCcsIG1vZGU9J3NjcmVlbnNob3QnCgkJCSkKCgkJCXJlcyA9IGdsLm5vbmRldC5leGVjX3Byb21wdCgKCQkJCSd3aGF0IGltYWdlIHNheXM/IHJlc3BvbmQgb25seSB3aXRoIGl0cyBjb250ZW50cycsIGltYWdlcz1baW1nXQoJCQkpCgoJCQlyZXR1cm4gJycuam9pbihjIGZvciBjIGluIHJlcy5zdHJpcCgpLmxvd2VyKCkgaWYgYy5pc2FscGhhKCkpCgoJCXJlcyA9IGdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEocnVuKQoJCXByaW50KHJlcywgZmlsZT1zeXMuc3RkZXJyKQoJCXByaW50KCdoZWxsb3dvcmxkJyBpbiByZXMpCgAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/unstable/nondet/web/get_webpage_text.0.hash b/tests/cases/unstable/nondet/web/get_webpage_text.0.hash deleted file mode 100644 index 9a6782d42..000000000 --- a/tests/cases/unstable/nondet/web/get_webpage_text.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDRlAEAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKaW1wb3J0IGh0bWwKZnJvbSBodG1sLnBhcnNlciBpbXBvcnQgSFRNTFBhcnNlcgoKZmNmID0gc2V0KFsnc2NyaXB0JywgJ2lmcmFtZSddKQoKCmNsYXNzIFNjcmlwdFJlbW92ZXIoSFRNTFBhcnNlcik6CglyZXN1bHQ6IGxpc3Rbc3RyXQoKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlzdXBlcigpLl9faW5pdF9fKCkKCQlzZWxmLnJlc3VsdCA9IFtdCgkJc2VsZi5pbl9zY3JpcHQgPSBGYWxzZQoKCWRlZiBoYW5kbGVfc3RhcnR0YWcoc2VsZiwgdGFnLCBhdHRycyk6CgkJaWYgdGFnLmxvd2VyKCkgaW4gZmNmOgoJCQlzZWxmLmluX3NjcmlwdCA9IFRydWUKCQllbGlmIG5vdCBzZWxmLmluX3NjcmlwdDoKCQkJc2VsZi5yZXN1bHQuYXBwZW5kKHNlbGYuZ2V0X3N0YXJ0dGFnX3RleHQoKSkKCglkZWYgaGFuZGxlX2VuZHRhZyhzZWxmLCB0YWcpOgoJCWlmIHRhZy5sb3dlcigpIGluIGZjZjoKCQkJc2VsZi5pbl9zY3JpcHQgPSBGYWxzZQoJCWVsaWYgbm90IHNlbGYuaW5fc2NyaXB0OgoJCQlzZWxmLnJlc3VsdC5hcHBlbmQoZic8L3t0YWd9PicpCgoJZGVmIGhhbmRsZV9kYXRhKHNlbGYsIGRhdGEpOgoJCWlmIG5vdCBzZWxmLmluX3NjcmlwdDoKCQkJc2VsZi5yZXN1bHQuYXBwZW5kKGRhdGEpCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG1haW4oc2VsZiwgbW9kZTogc3RyKToKCQlkZWYgcnVuKCkgLT4gc3RyOgoJCQlyZXMgPSBnbC5ub25kZXQud2ViLnJlbmRlcigKCQkJCSdodHRwczovL3Rlc3Qtc2VydmVyLmdlbmxheWVyLmNvbS9zdGF0aWMvZ2Vudm0vaGVsbG8uaHRtbCcsIG1vZGU9bW9kZQoJCQkpICAjIHR5cGU6IGlnbm9yZQoJCQlpZiBtb2RlID09ICdodG1sJzoKCQkJCXBhcnNlciA9IFNjcmlwdFJlbW92ZXIoKQoJCQkJcGFyc2VyLmZlZWQocmVzKQoJCQkJcmVzID0gJycuam9pbihwYXJzZXIucmVzdWx0KQoJCQlyZXR1cm4gcmVzCgoJCXByaW50KGdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEocnVuKS5zdHJpcCgpKQoAAAAAAAAAAAAAAAAF diff --git a/tests/cases/unstable/nondet/web/sandbox.0.hash b/tests/cases/unstable/nondet/web/sandbox.0.hash deleted file mode 100644 index 27195b0fe..000000000 --- a/tests/cases/unstable/nondet/web/sandbox.0.hash +++ /dev/null @@ -1 +0,0 @@ -LQEAABUVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDFlwBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmLCBldjogc3RyKToKCQlkZWYgcnVuX25kZXQoKToKCQkJZ2xiID0gZ2xvYmFscygpCgkJCXByaW50KGYne2dsLnZtLnNwYXduX3NhbmRib3gobGFtYmRhOiBldmFsKGV2LCBnbGIpKX0nKQoJCQlwcmludChqc29uLmxvYWRzLl9fbmFtZV9fKQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKHJ1bl9uZGV0KQoF diff --git a/tests/runner/ya_test_runner_plugins/integration.py b/tests/runner/ya_test_runner_plugins/integration.py index c7d10f121..df0204539 100644 --- a/tests/runner/ya_test_runner_plugins/integration.py +++ b/tests/runner/ya_test_runner_plugins/integration.py @@ -524,16 +524,10 @@ async def _run_single_step( bytes([public_abi.ResultCode.RETURN]) + gvm_calldata.encode(res['value']) ) elif res['kind'] == 'user_error': - if isinstance(res['value'], str): - encoded_nondet.append( - bytes([public_abi.ResultCode.USER_ERROR]) + res['value'].encode('utf-8') - ) - else: - encoded_nondet.append( - bytes([public_abi.ResultCode.USER_ERROR]) - + b'\x00\x00\x00\x00' - + gvm_calldata.encode(res['value']) - ) + encoded_nondet.append( + bytes([public_abi.ResultCode.USER_ERROR]) + + gvm_calldata.encode(res['value']) + ) elif res['kind'] == 'vm_error': encoded_nondet.append( bytes([public_abi.ResultCode.VM_ERROR]) + res['value'].encode('utf-8') From 09e9201a99c484e18ba658d07e8c9e49e4d2f032 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Wed, 24 Jun 2026 20:38:30 +0900 Subject: [PATCH 107/124] =?UTF-8?q?feat(sdk):=20add=20Yield=20and=20GetTim?= =?UTF-8?q?estamp=20gl=5Fcall=20methods=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GetTimestamp returns the transaction timestamp in deterministic mode and the real wall-clock time in non-deterministic mode; Yield is a reserved no-op for future waiting loops. --- .../03-wasi_genlayer_sdk/02-gl_call.rst | 50 +++++++++++++++++++ executor/crates/sdk-rs/src/abi/gl_call.rs | 10 ++++ executor/src/wasi/genlayer_sdk.rs | 17 +++++++ .../src/genlayer/vm/__init__.py | 27 ++++++++++ runners/support/versions/current.nix | 6 +-- 5 files changed, 107 insertions(+), 3 deletions(-) diff --git a/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst b/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst index d356e4f30..a20bc860a 100644 --- a/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst +++ b/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst @@ -498,3 +498,53 @@ Requirements #. GenVM version 0.1.10 or higher #. :term:`GenVM` implementation is allowed ignore this message + +``Yield`` Message +----------------- + +Cooperative yield. Currently a no-op and returns no value; it is reserved for future use in waiting loops. + +Payload +~~~~~~~ + +.. code-block:: + + { + "Yield": null + } + +.. note:: + + Implementations may choose to ignore this message. + +Requirements +~~~~~~~~~~~~ + +#. GenVM version 0.3.0 or higher +#. :term:`GenVM` implementation is allowed ignore this message + +.. _get-timestamp: + +``GetTimestamp`` Message +------------------------ + +Returns the current timestamp as the number of seconds since the Unix epoch. + +In :ref:`gvm-def-det-mode` it returns the transaction timestamp, keeping the value deterministic across validators. +In :ref:`gvm-def-non-det-mode` it returns the real wall-clock time. + +Payload +~~~~~~~ + +.. code-block:: + + { + "GetTimestamp": null + } + +Returns the timestamp encoded as a :ref:`Calldata Encoded ` number. + +Requirements +~~~~~~~~~~~~ + +#. GenVM version 0.3.0 or higher diff --git a/executor/crates/sdk-rs/src/abi/gl_call.rs b/executor/crates/sdk-rs/src/abi/gl_call.rs index c7b69fc97..c41c52f86 100644 --- a/executor/crates/sdk-rs/src/abi/gl_call.rs +++ b/executor/crates/sdk-rs/src/abi/gl_call.rs @@ -594,4 +594,14 @@ pub enum Message { Return(calldata::unparsed::Maybe), Trace(TracePayload), + + /// Cooperative yield. Currently a no-op; reserved for future use in + /// waiting loops. + Yield, + + /// Get the current timestamp as seconds since the Unix epoch. + /// + /// In [deterministic mode](super) returns the transaction timestamp; in + /// non-deterministic mode returns the real wall-clock time. + GetTimestamp, } diff --git a/executor/src/wasi/genlayer_sdk.rs b/executor/src/wasi/genlayer_sdk.rs index ce3c334ae..a9a2fe610 100644 --- a/executor/src/wasi/genlayer_sdk.rs +++ b/executor/src/wasi/genlayer_sdk.rs @@ -1352,6 +1352,8 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { path_in_vfs, } => self.map_file(runner, path_in_runner, path_in_vfs).await, gl_call::Message::Trace(message) => self.gl_call_trace(message).await, + gl_call::Message::Yield => Ok(file_fd_none()), + gl_call::Message::GetTimestamp => self.gl_call_get_timestamp().await, } } @@ -1597,6 +1599,21 @@ impl ContextVFS<'_> { } } + async fn gl_call_get_timestamp( + &mut self, + ) -> Result { + let timestamp = if self.context.data.conf.is_deterministic { + self.context.data.message_data.message.datetime.timestamp() + } else { + chrono::Utc::now().timestamp() + }; + + let data = calldata::encode(&calldata::Value::Number(num_bigint::BigInt::from( + timestamp, + ))); + self.place_content(vfs::FileContents::from(bytes::Bytes::from(data))) + } + async fn register_runner( &mut self, code: bytes::Bytes, diff --git a/runners/genlayer-py-std/src/genlayer/vm/__init__.py b/runners/genlayer-py-std/src/genlayer/vm/__init__.py index 151865933..8ea1805f1 100644 --- a/runners/genlayer-py-std/src/genlayer/vm/__init__.py +++ b/runners/genlayer-py-std/src/genlayer/vm/__init__.py @@ -20,6 +20,8 @@ 'Result', 'trace', 'trace_time_micro', + 'yield_', + 'get_timestamp', 'register_runner', 'map_file', 'ABI', @@ -35,6 +37,7 @@ import typing import dataclasses +import datetime import collections.abc from genlayer.types import Lazy @@ -347,6 +350,30 @@ def trace_time_micro() -> int: ).get() +def yield_() -> None: + """ + Cooperative yield. Currently a no-op, reserved for future use in waiting loops. + """ + wasi.gl_call(calldata.encode({'Yield': None})) + + +def get_timestamp() -> datetime.datetime: + """ + Returns the current timestamp as a timezone-aware ``datetime``. + + In deterministic mode it is the transaction timestamp; in + non-deterministic mode it is the real wall-clock time. + """ + return gl_call.gl_call_generic( + { + 'GetTimestamp': None, + }, + lambda x: datetime.datetime.fromtimestamp( + typing.cast(int, calldata.decode(x)), datetime.timezone.utc + ), + ).get() + + def register_runner(code: collections.abc.Buffer) -> str: """ Registers a runner archive at runtime and returns its ``custom:`` id. diff --git a/runners/support/versions/current.nix b/runners/support/versions/current.nix index 6f2fa9b77..67e8edc18 100644 --- a/runners/support/versions/current.nix +++ b/runners/support/versions/current.nix @@ -32,7 +32,7 @@ let }; genlayer-std = { - hash = "sha256-S4iSRVAS2wiavW9WmBriJ+svcJi6V67ybR/uSmYK+a0="; + hash = "sha256-YSkNZ3Q4V5YKvIahsccz/vrmMKzGHCudWmVqZKZsHMk="; }; genlayer-embeddings = { @@ -60,7 +60,7 @@ let wrappers = { __prefix = ""; py-genlayer = { - hash = "sha256-8Z0LeUX7ApxuBoi+Q/esPRLFO9i7ozaC2iEUb0idy8k="; + hash = "sha256-iUpzX4Xn1v4Ae+PDifOPNX1H2PFdMWBJCwffCclHgsk="; depends = [ cpython pyLibs.cloudpickle @@ -68,7 +68,7 @@ let ]; }; py-genlayer-multi = { - hash = "sha256-Vhwo4+ksqqRSp9BGDcHz461UiDXfb3g8rdLrqIAkLB0="; + hash = "sha256-UeVY7iVg4XkC8bEsxYXJEPj/fo8Med66a+kK63uIhEM="; depends = [ cpython pyLibs.cloudpickle From 7731c1c0bc703028bd4c98eb0e727c6ca95fad1b Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Wed, 24 Jun 2026 20:49:08 +0900 Subject: [PATCH 108/124] =?UTF-8?q?fix(abi):=20sync=20codegen=20root=5Foff?= =?UTF-8?q?sets=20input=20with=20major-first=20layout=20=F0=9F=90=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/codegen/data/public-abi.json | 10 +++++----- tests/runner/origin/public_abi.py | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/executor/codegen/data/public-abi.json b/executor/codegen/data/public-abi.json index 941740531..ad7993c6c 100644 --- a/executor/codegen/data/public-abi.json +++ b/executor/codegen/data/public-abi.json @@ -45,11 +45,11 @@ "name": "root_offsets", "repr": "u32", "values": { - "contract": 0, - "code": 1, - "locked_slots": 2, - "upgraders": 3, - "major": 4, + "major": 0, + "contract": 1, + "code": 2, + "locked_slots": 3, + "upgraders": 4, "code_slot": 5 } }, diff --git a/tests/runner/origin/public_abi.py b/tests/runner/origin/public_abi.py index a47567583..6c29cc2ce 100644 --- a/tests/runner/origin/public_abi.py +++ b/tests/runner/origin/public_abi.py @@ -34,11 +34,11 @@ class _MemoryLimiterConsts(typing.NamedTuple): class _RootOffsets(typing.NamedTuple): - CONTRACT: int = 0 - CODE: int = 1 - LOCKED_SLOTS: int = 2 - UPGRADERS: int = 3 - MAJOR: int = 4 + MAJOR: int = 0 + CONTRACT: int = 1 + CODE: int = 2 + LOCKED_SLOTS: int = 3 + UPGRADERS: int = 4 CODE_SLOT: int = 5 root_offsets: typing.Final = _RootOffsets() From 42befce79cf3993e10dee7987ff2c005c1e3f2f4 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Wed, 24 Jun 2026 20:49:12 +0900 Subject: [PATCH 109/124] =?UTF-8?q?docs(spec):=20user=5Ferror=20sub-VM=20r?= =?UTF-8?q?esult=20is=20calldata,=20not=20Rollback=20string=20=F0=9F=93=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../03-wasi_genlayer_sdk/03-schemas.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/03-schemas.rst b/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/03-schemas.rst index 469f97039..f127af46c 100644 --- a/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/03-schemas.rst +++ b/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/03-schemas.rst @@ -19,13 +19,13 @@ results through a file descriptor with the following binary format: Where ``result_code`` is a :ref:`gvm-def-enum-result-code`: - :ref:`gvm-def-enum-value-result-code-return` (``0``): Successful execution -- :ref:`gvm-def-enum-value-result-code-user-error` (``1``): Contract-initiated error via ``Rollback`` +- :ref:`gvm-def-enum-value-result-code-user-error` (``1``): Contract-initiated error - :ref:`gvm-def-enum-value-result-code-vm-error` (``2``): VM-level error The ``data`` portion depends on the result code: - **return**: :ref:`Calldata Encoded ` return value -- **user_error**: UTF-8 encoded error message string (from ``Rollback`` message) +- **user_error**: :ref:`Calldata Encoded ` error value - **vm_error**: UTF-8 encoded :ref:`gvm-def-str-trie-vm-error` string .. _gvm-def-module-result-encoding: From e60de7024ef7db843804d032e83819c421268ccb Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Wed, 24 Jun 2026 20:49:17 +0900 Subject: [PATCH 110/124] =?UTF-8?q?docs(spec):=20drop=20deprecated=20Rollb?= =?UTF-8?q?ack=20gl=5Fcall=20message=20=F0=9F=93=9D=F0=9F=94=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../03-wasi_genlayer_sdk/02-gl_call.rst | 5 ----- 1 file changed, 5 deletions(-) diff --git a/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst b/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst index a20bc860a..7e100c853 100644 --- a/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst +++ b/doc/website/src/spec/02-execution-environment/03-wasi_genlayer_sdk/02-gl_call.rst @@ -405,11 +405,6 @@ Requirements Topics must be exactly 32 bytes each. -``Rollback`` Message --------------------- - -Deprecated. Use ``UserError`` instead. - ``UserError`` Message --------------------- From 1850ea7adea90d0cc8dfeca3e81aa9fe47ec61c7 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Wed, 24 Jun 2026 20:49:25 +0900 Subject: [PATCH 111/124] =?UTF-8?q?docs(fees):=20document=20bucket=5Fno=20?= =?UTF-8?q?array=20form=20and=20atomic=20debits=20=F0=9F=93=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/website/src/impl-spec/04-fees.rst | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/doc/website/src/impl-spec/04-fees.rst b/doc/website/src/impl-spec/04-fees.rst index 5547da08e..36a240116 100644 --- a/doc/website/src/impl-spec/04-fees.rst +++ b/doc/website/src/impl-spec/04-fees.rst @@ -37,11 +37,14 @@ The ``fees`` block of the GenVM config (see ``doc/schemas/default-config.json``, per-bucket expressions can reference. ``bucket_no`` - Index into the ``Vec`` of bucket totals the host passes to - ``DataLimit::new``. Two bucket configs MAY share the same ``bucket_no``; in that - case both charge against the same reservoir. The ``message_fee`` / - ``message_receipt`` pair has special atomic-debit behaviour when they share a - bucket (``consume_message_fee`` in ``fees.rs:332``). + Either a single index, or an array of indices, into the ``Vec`` of bucket + totals the host passes to ``DataLimit::new``. With an array, a scalar ``delta_expr`` + result is charged against every listed bucket, while an array result is charged + element-wise (lengths must match); all debits in one charge are atomic + (all-or-nothing). Two bucket configs MAY share the same index; in that case both + charge against the same reservoir. The ``message_fee`` / ``message_receipt`` pair + has special atomic-debit behaviour when they share a bucket (``consume_message_fee`` + in ``fees.rs:332``). ``subtract_on_start_expr`` A bare numeric expression. Evaluated once at startup with ``node`` bound to the From 248d89ac4da8eb072a9699bbda5dc67b963d6903 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Wed, 24 Jun 2026 20:52:39 +0900 Subject: [PATCH 112/124] =?UTF-8?q?fix(schema):=20forbid=20reserved=20pref?= =?UTF-8?q?ixes=20in=20runner-id=20name:hash=20branch=20=F0=9F=94=92?= =?UTF-8?q?=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/schemas/runners.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/schemas/runners.json b/doc/schemas/runners.json index 12e474914..92646f114 100644 --- a/doc/schemas/runners.json +++ b/doc/schemas/runners.json @@ -17,7 +17,8 @@ "anyOf": [ { "pattern": "^[a-zA-Z0-9_-]+:[a-zA-Z0-9_=-]+$", - "description": "`name:hash` — packaged runner by human readable name and archive hash (in debug mode hash may be `test`/`latest`)" + "not": { "pattern": "^(contract|chain|custom):" }, + "description": "`name:hash` — packaged runner by human readable name and archive hash (in debug mode hash may be `test`/`latest`). `contract`/`chain`/`custom` are reserved and cannot be used as a name" }, { "const": "contract", From e9e8df4ce011dec6064df60d4a05fcce3bd18c2b Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Wed, 24 Jun 2026 20:55:17 +0900 Subject: [PATCH 113/124] =?UTF-8?q?docs(adr):=20bring=20runner-id=20ADR=20?= =?UTF-8?q?up=20to=20date=20with=20shipped=20chain=20form=20=F0=9F=93=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...11. runner ids and runtime registration.md | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/doc/adr/011. runner ids and runtime registration.md b/doc/adr/011. runner ids and runtime registration.md index 2eba1491f..1d7bb3b23 100644 --- a/doc/adr/011. runner ids and runtime registration.md +++ b/doc/adr/011. runner ids and runtime registration.md @@ -33,22 +33,25 @@ Rework runner ids into four explicit, specified forms (parsed in archive hash. In debug mode the hash may be `test`/`latest`. Unchanged. 2. `contract` — the runner of the contract currently being executed. Replaces the old, undocumented `` literal. -3. `chain:
::` — load a runner code blob directly from a +3. `chain:
[:[:]]` — load a runner code blob directly from a storage slot of an arbitrary contract: `
` is a `0x` 20 byte hex address, `a`/`f` selects accepted (latest non final) / finalized state, and - `` is a `0x` 32 byte hex slot id. The current contract's runner is the - canonical `chain:` id pointing at itself and the code slot, so `contract` and - an explicit self reference deduplicate in the cache. + `` is a 32 byte slot id encoded with GVM32 (Crockford Base32, not `0x` + hex). Both `` and `` are optional: `` defaults to `a` and + `` defaults to the target contract's resolved root code slot, so + `chain:
` and `chain:
:a` are valid shorthands. The current + contract's runner is the canonical `chain:` id pointing at itself and the code + slot, so `contract` and an explicit self reference deduplicate in the cache. 4. `custom:` — a runner registered at runtime, looked up in an in-memory map - keyed by ``. + keyed by `` (the GVM32-encoded SHA3-256 of the registered code). `contract`, `chain` and `custom` are reserved prefixes and cannot be used as human readable runner names. Add a `gl_call` `RegisterRunner { code: Bytes }` that parses `code` as a runner archive, charges its size against the memory limit and stores it under -`custom:`, where `` is a SHA3-256 of `code`. It returns the resulting -runner id. It is allowed only in deterministic mode and only when the contract +`custom:`, where `` is the GVM32-encoded SHA3-256 of `code`. It +returns the resulting runner id. It is allowed only in deterministic mode and only when the contract holds the new `register_runners` permission (permission char `u`). A friendly `genlayer.vm.register_runner(code) -> str` wrapper is exposed in the Python SDK. @@ -96,6 +99,12 @@ storage, it requires the `read_storage` permission. Exposed as loading in `executor/src/rt/supervisor/actions.rs`. - `chain:` reads code via a fresh `Storage` pointed at the target address/state and `read_code_at(slot)`. +- A dependency whose runner declares a public-ABI major different from the host's + `CURRENT_MAJOR` is rejected before its code is loaded, so an incompatible + on-chain runner cannot be pulled in via `Depends`/`With`. +- Runner ids are interned via a `StrSymbol` newtype so the runner maps stay + interned while lookups accept `&str` without interning untrusted input (an + attacker-supplied id cannot grow the global symbol table). - The `custom:` map lives on `Supervisor` (`register_custom_runner` / `get_custom_runner`). - Spec: `doc/schemas/runners.json` (`runner-id` type), From 17d84be95a15813de872a6c9c8a567f3cd4952fc Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Wed, 24 Jun 2026 21:01:12 +0900 Subject: [PATCH 114/124] =?UTF-8?q?fix(schema):=20allow=20optional=20state?= =?UTF-8?q?/slot=20in=20chain=20runner=20id=20=F0=9F=90=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/schemas/runners.json | 4 ++-- .../src/spec/02-execution-environment/04-runners.rst | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/doc/schemas/runners.json b/doc/schemas/runners.json index 92646f114..779fe9eda 100644 --- a/doc/schemas/runners.json +++ b/doc/schemas/runners.json @@ -25,8 +25,8 @@ "description": "the runner of the contract that is currently being executed" }, { - "pattern": "^chain:0x[0-9a-fA-F]{40}:[af]:[0-9abcdefghjkmnpqrstvwxyz]{52}$", - "description": "`chain:
::` — code blob read from a `0x` 20 byte address at a GVM32-encoded 32 byte slot, `a`=accepted / `f`=finalized" + "pattern": "^chain:0x[0-9a-fA-F]{40}(:[af](:[0-9abcdefghjkmnpqrstvwxyz]{52})?)?$", + "description": "`chain:
[:[:]]` — code blob read from a `0x` 20 byte address at a GVM32-encoded 32 byte slot, `a`=accepted / `f`=finalized. `` and `` are optional: `` defaults to `a` and `` to the target contract's root code slot" }, { "pattern": "^custom:[a-zA-Z0-9_=-]+$", diff --git a/doc/website/src/spec/02-execution-environment/04-runners.rst b/doc/website/src/spec/02-execution-environment/04-runners.rst index 6bcfb4134..d56882e36 100644 --- a/doc/website/src/spec/02-execution-environment/04-runners.rst +++ b/doc/website/src/spec/02-execution-environment/04-runners.rst @@ -17,10 +17,12 @@ forms (see the ``runner-id`` definition in the runner.json schema): - ``:`` — a packaged runner. ``human-readable-id`` is provided for convenience; ``hash`` is a hash of its contents (see `Hash Format`_). - ``contract`` — the runner of the contract currently being executed. -- ``chain:
::`` — a runner code blob read from a storage slot - of an arbitrary contract (``a`` = accepted, ``f`` = finalized). ``
`` is - a ``0x`` 20 byte hex address and ```` is a :term:`SlotID` encoded with - :doc:`../../04-contract-interface/06-gvm32`. +- ``chain:
[:[:]]`` — a runner code blob read from a storage + slot of an arbitrary contract (``a`` = accepted, ``f`` = finalized). ``
`` + is a ``0x`` 20 byte hex address and ```` is a :term:`SlotID` encoded with + :doc:`../../04-contract-interface/06-gvm32`. Both ```` and ```` are + optional: ```` defaults to ``a`` and ```` to the target contract's + root code slot. - ``custom:`` — a runner registered at runtime via the ``RegisterRunner`` ``gl_call``, looked up by its hash. From 635624bde3605997f80c2b8fa28e15e139d4c75e Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Wed, 24 Jun 2026 21:39:10 +0900 Subject: [PATCH 115/124] =?UTF-8?q?fix(runners):=20hide=20uncommitted=20de?= =?UTF-8?q?ploy=20code=20from=20on-chain=20runner=20reads=20=F0=9F=94=92?= =?UTF-8?q?=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A deploying contract's code was cached under the same `chain::a:` canonical key a `:a` (accepted) chain runner read resolves to, so a self-`CallContract` during `__init__` saw its own uncommitted code instead of erroring. Introduce `runners::ChainState` (Accepted | Finalized | Deploy) in place of `StorageType` in the runner `Id`. `Deploy` is never parsed from a runner id; the deploy VM resolves its own runner to it, and the archive is pre-populated into the runner cache at deploy time. A self/`:a` read of a contract mid-deploy now misses the cache, falls through to the (empty) host state, and fails with `invalid_contract`. --- executor/crates/common/src/sync.rs | 5 ++ executor/src/lib.rs | 10 +++ executor/src/rt/supervisor/actions.rs | 26 +++++--- executor/src/rt/supervisor/mod.rs | 30 ++++++++- executor/src/runners/cache.rs | 4 ++ executor/src/runners/mod.rs | 64 ++++++++++++++----- executor/src/wasi/genlayer_sdk.rs | 5 +- .../py/intercontract/call_self_view.0.stdout | 3 +- .../stable/py/intercontract/call_self_view.py | 10 ++- 9 files changed, 121 insertions(+), 36 deletions(-) diff --git a/executor/crates/common/src/sync.rs b/executor/crates/common/src/sync.rs index 4f5593eca..2159e512f 100644 --- a/executor/crates/common/src/sync.rs +++ b/executor/crates/common/src/sync.rs @@ -444,6 +444,11 @@ impl CacheMap { Self(dashmap::DashMap::new()) } + pub fn insert(&self, key: symbol_table::GlobalSymbol, value: T) { + self.0 + .insert(key, DArc::new(tokio::sync::OnceCell::new_with(Some(value)))); + } + pub async fn get_or_create( &self, key: symbol_table::GlobalSymbol, diff --git a/executor/src/lib.rs b/executor/src/lib.rs index 3d5050fcf..373836368 100644 --- a/executor/src/lib.rs +++ b/executor/src/lib.rs @@ -174,6 +174,16 @@ pub async fn run_with_impl( topmost_storage .write_major(genvm_common::version::CURRENT.major as u8) .await?; + + let code_slot = rt::vm::storage::default_code_slot(); + let archive = runners::parse(code.clone()).map_err(|e| { + rt::errors::VMError::wrap(public_abi::VmError::invalid_contract().val(), e) + })?; + supervisor.prepopulate_deploy_runner( + entry_data.message.contract_address, + code_slot, + archive, + ); } else { log_debug!("code is null"); } diff --git a/executor/src/rt/supervisor/actions.rs b/executor/src/rt/supervisor/actions.rs index 36b107877..ccd53df60 100644 --- a/executor/src/rt/supervisor/actions.rs +++ b/executor/src/rt/supervisor/actions.rs @@ -12,7 +12,7 @@ pub struct Ctx<'a, 'b> { pub visited: HashSet, pub contract_id: symbol_table::GlobalSymbol, pub contract_address: calldata::Address, - pub state: public_abi::StorageType, + pub state: runners::ChainState, pub code_slot: crate::SlotID, pub supervisor: &'a rt::supervisor::Supervisor, pub vm: &'b mut rt::vm::VMBase, @@ -60,7 +60,7 @@ enum ResolvedKind { /// address/state/`code_slot`. Chain { address: calldata::Address, - on: public_abi::StorageType, + on: runners::ChainState, slot: crate::SlotID, }, /// `custom:` — a runner registered at runtime. @@ -81,7 +81,7 @@ struct Resolved { async fn resolve_runner( supervisor: &rt::supervisor::Supervisor, contract_address: calldata::Address, - state: public_abi::StorageType, + state: runners::ChainState, code_slot: crate::SlotID, id: &str, ) -> anyhow::Result { @@ -132,10 +132,15 @@ async fn resolve_runner( } } runners::IdUnresolved::Chain { address, on, slot } => { - let on = on.unwrap_or(public_abi::StorageType::LatestNonFinal); + let on = on.unwrap_or(runners::ChainState::Accepted); let slot = match slot { Some(s) => s, None => { + let mode = on.host_storage_type().ok_or_else(|| { + make_malformed_runner_error( + "deploy-state chain runner cannot resolve its code slot from chain", + ) + })?; let mut storage = rt::vm::storage::Storage::new( address, supervisor.get_storage_limiter(), @@ -143,7 +148,7 @@ async fn resolve_runner( supervisor.host.clone(), crate::wasi::genlayer_sdk::ReadToken { account: address, - mode: on, + mode, }, ), ); @@ -217,6 +222,11 @@ async fn get_arch( .get_or_create( id, || async { + let mode = on.host_storage_type().ok_or_else(|| { + make_malformed_runner_error( + "deploy-state chain runner is not available on chain", + ) + })?; let mut storage = rt::vm::storage::Storage::new( address, supervisor.get_storage_limiter(), @@ -224,7 +234,7 @@ async fn get_arch( supervisor.host.clone(), crate::wasi::genlayer_sdk::ReadToken { account: address, - mode: on, + mode, }, ), ); @@ -279,7 +289,7 @@ async fn get_arch( pub(crate) async fn load_runner( supervisor: &rt::supervisor::Supervisor, contract_address: calldata::Address, - state: public_abi::StorageType, + state: runners::ChainState, code_slot: crate::SlotID, limiter: &rt::memlimiter::Limiter, id: &str, @@ -382,7 +392,7 @@ pub(crate) async fn map_runner_file( preview1: &mut crate::wasi::preview1::Context, limiter: &rt::memlimiter::Limiter, contract_address: calldata::Address, - state: public_abi::StorageType, + state: runners::ChainState, code_slot: crate::SlotID, runner: &str, path_in_runner: &str, diff --git a/executor/src/rt/supervisor/mod.rs b/executor/src/rt/supervisor/mod.rs index effdb2d31..ec88a6ef0 100644 --- a/executor/src/rt/supervisor/mod.rs +++ b/executor/src/rt/supervisor/mod.rs @@ -233,6 +233,21 @@ impl Supervisor { self.custom_runners.get(&hash).map(|r| r.clone()) } + pub fn prepopulate_deploy_runner( + &self, + address: calldata::Address, + code_slot: crate::SlotID, + archive: runners::Archive, + ) { + let id = runners::Id::Chain { + address, + on: runners::ChainState::Deploy, + slot: code_slot, + } + .canonical(); + self.runner_cache.put(id, archive); + } + /// Registers a runner from its `code`, returning the `custom:` id it can /// be referenced by. /// @@ -458,9 +473,20 @@ async fn apply_contract_actions_inner( .data .conf .code_slot = code_slot; + let is_init = vm + .vm_base + .store + .data() + .genlayer_ctx + .genlayer_sdk + .data + .message_data + .message + .is_init; + let runner_state = runners::ChainState::for_vm(is_init, state); let contract_id = runners::Id::Chain { address: contract_address, - on: state, + on: runner_state, slot: code_slot, } .canonical(); @@ -523,7 +549,7 @@ async fn apply_contract_actions_inner( visited: HashSet::new(), contract_id, contract_address, - state, + state: runner_state, code_slot, supervisor: zelf, vm: &mut vm.vm_base, diff --git a/executor/src/runners/cache.rs b/executor/src/runners/cache.rs index c516f1ae8..0e00a6235 100644 --- a/executor/src/runners/cache.rs +++ b/executor/src/runners/cache.rs @@ -104,6 +104,10 @@ impl Reader { &self.runners_data_path } + pub fn put(&self, id: symbol_table::GlobalSymbol, archive: Archive) { + self.cache.insert(id, ArchiveCache::new(id, archive)); + } + pub async fn get_or_create( &self, name: symbol_table::GlobalSymbol, diff --git a/executor/src/runners/mod.rs b/executor/src/runners/mod.rs index 4c05812d2..4ddcdacaf 100644 --- a/executor/src/runners/mod.rs +++ b/executor/src/runners/mod.rs @@ -23,6 +23,42 @@ pub fn append_runner_subpath(id: &str, hash: &str, path: &mut std::path::PathBuf path.push(&hash[2..]); } +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ChainState { + Accepted, + Finalized, + Deploy, +} + +impl ChainState { + pub fn for_vm(is_init: bool, state: crate::public_abi::StorageType) -> Self { + if is_init { + ChainState::Deploy + } else { + match state { + crate::public_abi::StorageType::LatestFinal => ChainState::Finalized, + _ => ChainState::Accepted, + } + } + } + + pub fn host_storage_type(self) -> Option { + match self { + ChainState::Accepted => Some(crate::public_abi::StorageType::LatestNonFinal), + ChainState::Finalized => Some(crate::public_abi::StorageType::LatestFinal), + ChainState::Deploy => None, + } + } + + fn canonical_char(self) -> char { + match self { + ChainState::Accepted => 'a', + ChainState::Finalized => 'f', + ChainState::Deploy => 'd', + } + } +} + /// A parsed runner id. Runner ids come in the following forms: /// /// - `name:hash` — a packaged runner identified by its human readable name and @@ -45,7 +81,7 @@ pub enum IdUnresolved { Contract, Chain { address: calldata::Address, - on: Option, + on: Option, slot: Option, }, Custom { @@ -60,7 +96,7 @@ pub enum Id { }, Chain { address: calldata::Address, - on: crate::public_abi::StorageType, + on: ChainState, slot: crate::SlotID, }, Custom { @@ -78,7 +114,7 @@ impl IdUnresolved { pub fn resolve( self, contract_address: calldata::Address, - state: crate::public_abi::StorageType, + state: ChainState, code_slot: crate::SlotID, ) -> IdUnresolved { match self { @@ -104,18 +140,12 @@ impl Id { id.push_str(&hash.to_gvm32()); symbol_table::GlobalSymbol::from(id) } - Id::Chain { address, on, slot } => { - let on = match *on { - crate::public_abi::StorageType::LatestFinal => 'f', - _ => 'a', - }; - symbol_table::GlobalSymbol::from(format!( - "chain:0x{}:{}:{}", - address.checksum_hex_string(), - on, - genlayer_sdk::gvm32::encode(&slot.raw()) - )) - } + Id::Chain { address, on, slot } => symbol_table::GlobalSymbol::from(format!( + "chain:0x{}:{}:{}", + address.checksum_hex_string(), + on.canonical_char(), + genlayer_sdk::gvm32::encode(&slot.raw()) + )), Id::Custom { hash } => { let mut id = String::from("custom:"); id.push_str(&hash.to_gvm32()); @@ -155,8 +185,8 @@ pub fn parse_runner_id(id: &str) -> Option { let address = calldata::Address::from(parse_hex_fixed::<20>(address)?); let on = match on_str { - Some("a") | None => Some(crate::public_abi::StorageType::LatestNonFinal), - Some("f") => Some(crate::public_abi::StorageType::LatestFinal), + Some("a") | None => Some(ChainState::Accepted), + Some("f") => Some(ChainState::Finalized), _ => return None, }; let slot = match slot_str { diff --git a/executor/src/wasi/genlayer_sdk.rs b/executor/src/wasi/genlayer_sdk.rs index a9a2fe610..e1dd7c969 100644 --- a/executor/src/wasi/genlayer_sdk.rs +++ b/executor/src/wasi/genlayer_sdk.rs @@ -1658,7 +1658,10 @@ impl ContextVFS<'_> { let is_det = self.context.data.conf.is_deterministic; let limiter = supervisor.limiter.get(is_det); let contract_address = self.context.data.message_data.message.contract_address; - let state = self.context.data.conf.state_mode; + let state = crate::runners::ChainState::for_vm( + self.context.data.message_data.message.is_init, + self.context.data.conf.state_mode, + ); let code_slot = self.context.data.conf.code_slot; let available_custom = self.context.data.accumulator.custom_runners.clone(); diff --git a/tests/cases/stable/py/intercontract/call_self_view.0.stdout b/tests/cases/stable/py/intercontract/call_self_view.0.stdout index 986740094..82f34ded9 100644 --- a/tests/cases/stable/py/intercontract/call_self_view.0.stdout +++ b/tests/cases/stable/py/intercontract/call_self_view.0.stdout @@ -1,2 +1 @@ -self view -> 30 -executed with `Return(null)` +executed with `VMError("invalid_contract absent_runner_comment")` diff --git a/tests/cases/stable/py/intercontract/call_self_view.py b/tests/cases/stable/py/intercontract/call_self_view.py index 931b28767..78ce8339c 100644 --- a/tests/cases/stable/py/intercontract/call_self_view.py +++ b/tests/cases/stable/py/intercontract/call_self_view.py @@ -5,12 +5,10 @@ class Contract(gl.contract.Contract): def __init__(self): - # self-CallContract into our own view method during deploy; arguably a - # footgun that should be forbidden - try: - print('self view ->', gl.contract.get_at(self.address).view().read30()) - except Exception as e: - print('self view failed:', type(e).__name__) + # self-CallContract into our own view method during deploy: our code is + # not committed on-chain yet, so it is not visible as an `:a` runner and + # this fails with `invalid_contract` (aborting the deploy) + print('self view ->', gl.contract.get_at(self.address).view().read30()) @gl.public.view def read30(self) -> int: From 1c4ff13089c3ce74629855f1de1e514f754d4ae0 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Wed, 24 Jun 2026 23:08:11 +0900 Subject: [PATCH 116/124] =?UTF-8?q?refactor(runners):=20thread=20the=20res?= =?UTF-8?q?olved=20runner=20id=20through=20the=20VM=20config=20=E2=99=BB?= =?UTF-8?q?=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace `Config.code_slot` with `Config.topmost_runner_id: runners::Id` so a VM carries the fully-resolved id of the runner it loads, not just a slot. Split `resolve_runner` into `resolve_runner_id` (str -> Id) plus a `Resolved` wrapper; `load_runner`/`map_runner_file` now take an already-resolved id. `Id` gains `Clone`/`Serialize`/`Encode`. Check the contract major *before* trusting the host-read code-slot pointer: add `Storage::check_major_and_resolve_code_slot`, used by both the top-level call and `CallContract`. A VMError raised while preparing the top-level contract (bad code, major mismatch, missing slot) is now surfaced as a VMError result via `FullResult::empty_from` instead of bubbling up as an internal error. Add a test for running a registered custom runner inside a sandbox. It is test-first: the sandbox `runner` parameter that drives it is not wired yet, so it stays red until that lands. --- executor/Cargo.lock | 1 + executor/crates/common/Cargo.toml | 1 + executor/crates/common/src/bytes32.rs | 23 +++- executor/src/lib.rs | 73 +++++++--- executor/src/rt/supervisor/actions.rs | 100 +++++++------- executor/src/rt/supervisor/mod.rs | 126 ++++-------------- executor/src/rt/vm/storage.rs | 21 ++- executor/src/runners/mod.rs | 45 ++++--- executor/src/wasi/base.rs | 6 +- executor/src/wasi/genlayer_sdk.rs | 68 +++++----- executor/src/wasi/mod.rs | 6 +- modules/implementation/Cargo.lock | 1 + .../runners/sandbox_custom_runner.0.stdout | 3 + .../runners/sandbox_custom_runner.jsonnet | 3 + .../stable/runners/sandbox_custom_runner.py | 13 ++ 15 files changed, 256 insertions(+), 234 deletions(-) create mode 100644 tests/cases/stable/runners/sandbox_custom_runner.0.stdout create mode 100644 tests/cases/stable/runners/sandbox_custom_runner.jsonnet create mode 100644 tests/cases/stable/runners/sandbox_custom_runner.py diff --git a/executor/Cargo.lock b/executor/Cargo.lock index f1a0232e7..a347bf38a 100644 --- a/executor/Cargo.lock +++ b/executor/Cargo.lock @@ -1066,6 +1066,7 @@ dependencies = [ "rpds", "rustix 0.38.44", "serde", + "serde_bytes", "serde_json", "serde_yaml", "symbol_table", diff --git a/executor/crates/common/Cargo.toml b/executor/crates/common/Cargo.toml index 218d70b0b..76418ca91 100644 --- a/executor/crates/common/Cargo.toml +++ b/executor/crates/common/Cargo.toml @@ -16,6 +16,7 @@ regex = "1.11.1" serde = { version = "1.0.219", features = ["derive", "rc"] } serde_json = "1.0.140" serde_yaml = "0.9.34" +serde_bytes = "0.11.17" tokio = { version = "1.44.1", features = ["rt", "rt-multi-thread", "net", "time", "macros", "sync"], default-features = false} num-bigint = { version = "0.4.6", features = ["serde"] } num-rational = { version = "0.4", default-features = false, features = ["num-bigint"] } diff --git a/executor/crates/common/src/bytes32.rs b/executor/crates/common/src/bytes32.rs index 41713e0a5..a3d9223ff 100644 --- a/executor/crates/common/src/bytes32.rs +++ b/executor/crates/common/src/bytes32.rs @@ -3,9 +3,28 @@ /// A 32-byte hash value. Formats (and parses) as GVM32 / Crockford Base32 (see /// [`genlayer_sdk::gvm32`]). #[derive( - Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, serde::Serialize, serde::Deserialize, + Clone, + Copy, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, + serde::Serialize, + serde::Deserialize, + genlayer_calldata::Encode, + genlayer_calldata::Decode, + arbitrary::Arbitrary, )] -pub struct Bytes32Hash(pub [u8; 32]); +#[repr(transparent)] +pub struct Bytes32Hash( + #[serde(with = "serde_bytes")] + #[calldata( + serialize_with = genlayer_calldata::codec::as_bytes::serialize, + deserialize_with = genlayer_calldata::codec::as_bytes::deserialize, + )] + pub [u8; 32], +); impl Bytes32Hash { pub const ZERO: Self = Self([0; 32]); diff --git a/executor/src/lib.rs b/executor/src/lib.rs index 373836368..8cc54f8ae 100644 --- a/executor/src/lib.rs +++ b/executor/src/lib.rs @@ -165,28 +165,57 @@ pub async fn run_with_impl( ), ); - if let Some(code) = &entry_data.code { - log_debug!("using provided code for execution"); - - topmost_storage.write_code(code).await?; - // Record the major this contract is deployed for, so later runs can - // verify major compatibility (see `read_major` / major_mismatch check). - topmost_storage - .write_major(genvm_common::version::CURRENT.major as u8) - .await?; - - let code_slot = rt::vm::storage::default_code_slot(); - let archive = runners::parse(code.clone()).map_err(|e| { - rt::errors::VMError::wrap(public_abi::VmError::invalid_contract().val(), e) - })?; - supervisor.prepopulate_deploy_runner( - entry_data.message.contract_address, - code_slot, - archive, - ); - } else { - log_debug!("code is null"); + let topmost_runner_id = match async { + anyhow::Ok(if let Some(code) = &entry_data.code { + log_debug!("using provided code for execution"); + + topmost_storage.write_code(code).await?; + // Record the major this contract is deployed for, so later runs can + // verify major compatibility (see `read_major` / major_mismatch check). + topmost_storage + .write_major(genvm_common::version::CURRENT.major as u8) + .await?; + + let code_slot = rt::vm::storage::default_code_slot(); + let archive = runners::parse(code.clone()).map_err(|e| { + rt::errors::VMError::wrap(public_abi::VmError::invalid_contract().val(), e) + })?; + supervisor.prepopulate_deploy_runner( + entry_data.message.contract_address, + code_slot, + archive, + ); + + runners::Id::Chain { + address: entry_data.message.contract_address, + on: runners::ChainState::Deploy, + slot: code_slot, + } + } else { + log_debug!("code is null"); + + let code_slot = topmost_storage.check_major_and_resolve_code_slot().await?; + + runners::Id::Chain { + address: entry_data.message.contract_address, + on: runners::ChainState::Accepted, + slot: code_slot, + } + }) } + .await + { + Ok(id) => id, + // A VMError raised while preparing the contract (bad code, major + // mismatch, missing code slot) is a contract error, not an internal + // failure: surface it as a VMError result. Genuine internal errors still + // propagate via `?`. + Err(e) => { + return Ok(rt::vm::FullResult::empty_from( + rt::errors::unwrap_vm_errors(e.into())?, + )); + } + }; let data_fees_limit = supervisor.shared_data.gep(|x| &x.data_fees_limit); @@ -203,7 +232,7 @@ pub async fn run_with_impl( can_spawn_nondet: permissions.contains("n"), can_register_runners: permissions.contains("u"), state_mode: crate::public_abi::StorageType::Default, - code_slot: crate::SlotID::ZERO, + topmost_runner_id, }, message_data: ExtendedMessage { message: entry_data.message, diff --git a/executor/src/rt/supervisor/actions.rs b/executor/src/rt/supervisor/actions.rs index ccd53df60..89fac2d3c 100644 --- a/executor/src/rt/supervisor/actions.rs +++ b/executor/src/rt/supervisor/actions.rs @@ -10,10 +10,7 @@ use wiggle::error::Context as _; pub struct Ctx<'a, 'b> { pub env: BTreeMap, pub visited: HashSet, - pub contract_id: symbol_table::GlobalSymbol, - pub contract_address: calldata::Address, - pub state: runners::ChainState, - pub code_slot: crate::SlotID, + pub topmost_runner_id: runners::Id, pub supervisor: &'a rt::supervisor::Supervisor, pub vm: &'b mut rt::vm::VMBase, } @@ -74,25 +71,44 @@ struct Resolved { kind: ResolvedKind, } +impl From for Resolved { + fn from(id: runners::Id) -> Self { + let kind = match &id { + runners::Id::Builtin { name, hash } => ResolvedKind::Disk { + name: name.clone(), + hash: hash.clone(), + }, + runners::Id::Chain { address, on, slot } => ResolvedKind::Chain { + address: *address, + on: *on, + slot: *slot, + }, + runners::Id::Custom { hash } => ResolvedKind::Custom { hash: *hash }, + }; + Self { + id: id.canonical(), + kind, + } + } +} + /// Resolves a runner id to its canonical cache key and load strategy. /// /// Free-standing so it can be shared between contract initialization /// ([`Ctx`]) and runtime `gl_call`s ([`load_runner`]). -async fn resolve_runner( +pub(crate) async fn resolve_runner_id( supervisor: &rt::supervisor::Supervisor, - contract_address: calldata::Address, - state: runners::ChainState, - code_slot: crate::SlotID, + topmost_runner_id: &runners::Id, id: &str, -) -> anyhow::Result { +) -> anyhow::Result { let Some(parsed) = runners::parse_runner_id(id) else { return Err(make_malformed_runner_error( "runner id doesn't match expected format", )); }; - let resolved: runners::Id = match parsed.resolve(contract_address, state, code_slot) { - runners::IdUnresolved::Contract => unreachable!("contract is resolved to chain"), + let resolved: runners::Id = match parsed { + runners::IdUnresolved::Contract => topmost_runner_id.clone(), runners::IdUnresolved::Builtin { name, hash } => { let hash: Bytes32Hash = if hash == "test" || hash == "latest" { if !supervisor.shared_data.debug_mode.allows_latest_resolution() { @@ -172,13 +188,17 @@ async fn resolve_runner( } }; - let id = resolved.canonical(); - let kind = match resolved { - runners::Id::Builtin { name, hash } => ResolvedKind::Disk { name, hash }, - runners::Id::Chain { address, on, slot } => ResolvedKind::Chain { address, on, slot }, - runners::Id::Custom { hash } => ResolvedKind::Custom { hash }, - }; - Ok(Resolved { id, kind }) + Ok(resolved) +} + +async fn resolve_runner( + supervisor: &rt::supervisor::Supervisor, + topmost_runner_id: &runners::Id, + id: &str, +) -> anyhow::Result { + Ok(resolve_runner_id(supervisor, topmost_runner_id, id) + .await? + .into()) } /// Loads (and caches) the archive for an already-resolved runner. @@ -288,17 +308,15 @@ async fn get_arch( #[allow(clippy::too_many_arguments)] pub(crate) async fn load_runner( supervisor: &rt::supervisor::Supervisor, - contract_address: calldata::Address, - state: runners::ChainState, - code_slot: crate::SlotID, limiter: &rt::memlimiter::Limiter, - id: &str, + id: runners::Id, available_custom: &rpds::HashTrieSet, ) -> anyhow::Result<( symbol_table::GlobalSymbol, sync::DArc, )> { - let resolved = resolve_runner(supervisor, contract_address, state, code_slot, id).await?; + let resolved: Resolved = id.into(); + // Custom runners are execution-scoped: a `custom:` is only resolvable // by a scope that registered it (or inherited it from a det parent), so the // shared registry cannot leak a runner across unrelated scopes (e.g. nondet). @@ -381,47 +399,27 @@ pub(crate) fn map_archive_file( Ok(()) } -/// Resolves `runner` (relative to the contract at `contract_address`) and maps -/// one of its files into `preview1` at runtime. This keeps all runner-resolution -/// knowledge in this module: callers (e.g. the `MapFile` `gl_call`) only supply -/// VM context and delegate, instead of stitching the resolution together -/// themselves. +/// Maps one of an already-resolved `runner`'s files into `preview1` at runtime. +/// This keeps all runner-loading knowledge in this module: callers (e.g. the +/// `MapFile` `gl_call`) resolve the id and delegate, instead of stitching the +/// archive loading together themselves. #[allow(clippy::too_many_arguments)] pub(crate) async fn map_runner_file( supervisor: &rt::supervisor::Supervisor, preview1: &mut crate::wasi::preview1::Context, limiter: &rt::memlimiter::Limiter, - contract_address: calldata::Address, - state: runners::ChainState, - code_slot: crate::SlotID, - runner: &str, + runner: runners::Id, path_in_runner: &str, path_in_vfs: &str, available_custom: &rpds::HashTrieSet, ) -> anyhow::Result<()> { - let (_id, arch) = load_runner( - supervisor, - contract_address, - state, - code_slot, - limiter, - runner, - available_custom, - ) - .await?; + let (_id, arch) = load_runner(supervisor, limiter, runner, available_custom).await?; map_archive_file(preview1, limiter, &arch, path_in_runner, path_in_vfs) } impl Ctx<'_, '_> { async fn resolve_runner(&self, id: &str) -> anyhow::Result { - resolve_runner( - self.supervisor, - self.contract_address, - self.state, - self.code_slot, - id, - ) - .await + resolve_runner(self.supervisor, &self.topmost_runner_id, id).await } async fn get_arch( @@ -514,7 +512,7 @@ impl Ctx<'_, '_> { self.supervisor .compile_wasm(contents.as_ref(), wasm_key.as_str()) .await - .with_context(|| format!("compiling wasm {path:?} of {}", self.contract_id)) + .with_context(|| format!("compiling wasm {path:?} of {}", current)) }) .await?; diff --git a/executor/src/rt/supervisor/mod.rs b/executor/src/rt/supervisor/mod.rs index ec88a6ef0..1ee0ee120 100644 --- a/executor/src/rt/supervisor/mod.rs +++ b/executor/src/rt/supervisor/mod.rs @@ -359,7 +359,7 @@ pub async fn spawn( }); } - let config_copy = vm.conf; + let config_copy = vm.conf.clone(); let engine = zelf.engines.get(vm.conf.is_deterministic); @@ -408,32 +408,9 @@ pub async fn apply_contract_actions( zelf: &std::sync::Arc, mut vm: rt::vm::VM<()>, ) -> std::result::Result, rt::SpawnError> { - let contract_address = vm - .vm_base - .store - .data() - .genlayer_ctx - .genlayer_sdk - .data - .message_data - .message - .contract_address; - - let contract_state = vm - .vm_base - .store - .data() - .genlayer_ctx - .genlayer_sdk - .data - .conf - .state_mode; - let limiter = vm.vm_base.store.data_mut().limits.clone(); - let res = - apply_contract_actions_inner(zelf, &mut vm, contract_address, contract_state, limiter) - .await; + let res = apply_contract_actions_inner(zelf, &mut vm, limiter).await; match res { Ok(inst) => Ok(rt::vm::VM { @@ -450,58 +427,16 @@ pub async fn apply_contract_actions( async fn apply_contract_actions_inner( zelf: &std::sync::Arc, vm: &mut rt::vm::VM<()>, - contract_address: calldata::Address, - state: public_abi::StorageType, limiter: rt::memlimiter::Limiter, ) -> anyhow::Result { - let code_slot = vm - .vm_base - .store - .data_mut() - .genlayer_ctx - .genlayer_sdk - .data - .storage - .resolve_code_slot() - .await - .with_context(|| "resolving contract code slot")?; - vm.vm_base - .store - .data_mut() - .genlayer_ctx - .genlayer_sdk - .data - .conf - .code_slot = code_slot; - let is_init = vm - .vm_base - .store - .data() - .genlayer_ctx - .genlayer_sdk - .data - .message_data - .message - .is_init; - let runner_state = runners::ChainState::for_vm(is_init, state); - let contract_id = runners::Id::Chain { - address: contract_address, - on: runner_state, - slot: code_slot, - } - .canonical(); - - let contract_major = vm - .vm_base - .store - .data_mut() - .genlayer_ctx - .genlayer_sdk - .data + let data = &mut vm.vm_base.store.data_mut().genlayer_ctx.genlayer_sdk.data; + + let topmost_runner_id = data.conf.topmost_runner_id.clone(); + let contract_major = data .storage .read_major() .await - .with_context(|| format!("reading contract major for {contract_id}"))?; + .with_context(|| format!("reading contract major for {topmost_runner_id}"))?; let node_major = genvm_common::version::CURRENT.major; if contract_major as u16 != node_major { return Err(rt::errors::VMError( @@ -513,49 +448,36 @@ async fn apply_contract_actions_inner( .into()); } - let arch = zelf - .runner_cache - .get_or_create( - contract_id, - || async { - let code = vm - .vm_base - .store - .data_mut() - .genlayer_ctx - .genlayer_sdk - .data - .storage - .read_code_at(code_slot, &limiter) - .await - .with_context(|| format!("reading contract code for {contract_id}"))?; - - runners::parse(bytes::Bytes::from(code)) - .with_context(|| format!("parsing contract runner for {contract_id}")) - }, - &limiter, - ) - .await - .map_err(|e| rt::errors::VMError::wrap(public_abi::VmError::invalid_contract().val(), e))?; + let topmost_runner_id = data.conf.topmost_runner_id.clone(); + + let arch = actions::load_runner( + zelf, + &limiter, + topmost_runner_id.clone(), + &data.accumulator.custom_runners, + ) + .await + .with_context(|| format!("getting runner for {topmost_runner_id}"))? + .1; let actions = arch .get_actions() .await - .with_context(|| format!("loading init actions for contract {contract_id}")) + .with_context(|| format!("loading init actions for contract {topmost_runner_id}")) .map_err(|e| rt::errors::VMError::wrap(public_abi::VmError::invalid_contract().val(), e))?; let mut ctx = actions::Ctx { env: BTreeMap::new(), visited: HashSet::new(), - contract_id, - contract_address, - state: runner_state, - code_slot, + topmost_runner_id: topmost_runner_id.clone(), supervisor: zelf, vm: &mut vm.vm_base, }; - let inst = match ctx.apply(&actions, contract_id, &arch).await { + let inst = match ctx + .apply(&actions, topmost_runner_id.canonical(), &arch) + .await + { Ok(Some(inst)) => inst, Ok(None) => { return Err(anyhow::anyhow!( diff --git a/executor/src/rt/vm/storage.rs b/executor/src/rt/vm/storage.rs index b96839cc2..3ae2383d4 100644 --- a/executor/src/rt/vm/storage.rs +++ b/executor/src/rt/vm/storage.rs @@ -5,7 +5,7 @@ use const_lru::ConstLru; use genlayer_sdk::abi; use genvm_common::{calldata, sync}; -use crate::{public_abi::root_offsets, rt, SlotID}; +use crate::{public_abi::root_offsets, rt, runners, SlotID}; #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] #[repr(C)] @@ -446,6 +446,25 @@ impl Storage { } } + /// Verifies the contract's major version matches this node's, then resolves + /// its code slot. The major is checked *first*, before trusting the + /// host-read code-slot pointer; on mismatch a `major_mismatch` [`VMError`] + /// is returned so the caller surfaces it as a contract error. + pub async fn check_major_and_resolve_code_slot(&mut self) -> anyhow::Result { + let contract_major = self.read_major().await?; + let node_major = genvm_common::version::CURRENT.major; + if contract_major as u16 != node_major { + return Err(rt::errors::VMError( + abi::consts::VmError::invalid_contract().major_mismatch(), + Some(anyhow::anyhow!( + "contract major {contract_major} != node major {node_major}" + )), + ) + .into()); + } + self.resolve_code_slot().await + } + pub async fn read_code_at( &mut self, code_slot: SlotID, diff --git a/executor/src/runners/mod.rs b/executor/src/runners/mod.rs index 4ddcdacaf..668c2c007 100644 --- a/executor/src/runners/mod.rs +++ b/executor/src/runners/mod.rs @@ -23,7 +23,7 @@ pub fn append_runner_subpath(id: &str, hash: &str, path: &mut std::path::PathBuf path.push(&hash[2..]); } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, genlayer_calldata::Encode)] pub enum ChainState { Accepted, Finalized, @@ -89,6 +89,7 @@ pub enum IdUnresolved { }, } +#[derive(Debug, Clone)] pub enum Id { Builtin { name: symbol_table::GlobalSymbol, @@ -104,27 +105,21 @@ pub enum Id { }, } -impl IdUnresolved { - /// Resolves a parsed runner id against the currently executing contract. - /// - /// The only resolution step is `contract` → the `chain:` id pointing at this - /// contract's own code (its address, state and resolved `code_slot`), so the - /// current contract is loaded through the exact same path as any other - /// `chain:` runner. - pub fn resolve( - self, - contract_address: calldata::Address, - state: ChainState, - code_slot: crate::SlotID, - ) -> IdUnresolved { - match self { - IdUnresolved::Contract => IdUnresolved::Chain { - address: contract_address, - on: Some(state), - slot: Some(code_slot), - }, - other => other, - } +impl serde::Serialize for Id { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.canonical().as_str()) + } +} + +impl calldata::codec::Encode for Id { + type Error = ::Error; + + fn encode(&self, encoder: &mut genlayer_calldata::Encoder) -> Result<(), Self::Error> { + let canonical = self.canonical(); + encoder.push_str(canonical.as_str()) } } @@ -155,6 +150,12 @@ impl Id { } } +impl std::fmt::Display for Id { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(self.canonical().as_str()) + } +} + fn is_hash_char(c: char) -> bool { c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '=' } diff --git a/executor/src/wasi/base.rs b/executor/src/wasi/base.rs index ca395e322..8bc391773 100644 --- a/executor/src/wasi/base.rs +++ b/executor/src/wasi/base.rs @@ -1,8 +1,8 @@ use serde::Serialize; -use crate::public_abi; +use crate::{public_abi, runners}; -#[derive(Clone, Copy, Serialize, genlayer_calldata::Encode)] +#[derive(Clone, Serialize, genlayer_calldata::Encode)] pub struct Config { pub needs_error_fingerprint: bool, pub is_deterministic: bool, @@ -13,7 +13,7 @@ pub struct Config { pub can_call_others: bool, pub can_register_runners: bool, pub state_mode: public_abi::StorageType, - pub code_slot: crate::SlotID, + pub topmost_runner_id: runners::Id, } impl Config { diff --git a/executor/src/wasi/genlayer_sdk.rs b/executor/src/wasi/genlayer_sdk.rs index e1dd7c969..972622832 100644 --- a/executor/src/wasi/genlayer_sdk.rs +++ b/executor/src/wasi/genlayer_sdk.rs @@ -9,7 +9,7 @@ use sha3::digest::Update; use wiggle::GuestError; use crate::host::{self, SlotID}; -use crate::{anyhow_to_wasmtime, calldata, public_abi, rt, wasi}; +use crate::{anyhow_to_wasmtime, calldata, public_abi, rt, runners, wasi}; use genlayer_calldata::codec::Encode; pub use genlayer_sdk::abi::entry::ExtendedMessage; @@ -715,7 +715,7 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { let supervisor = self.context.data.supervisor.clone(); - let my_conf = self.context.data.conf; + let my_conf = self.context.data.conf.clone(); let calldata_encoded = calldata::encode_obj(&calldata); @@ -728,6 +728,23 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { let calldata_encoded = calldata::encode_obj(&calldata); + let mut child_storage = rt::vm::storage::Storage::new( + address, + supervisor.get_storage_limiter(), + StorageHostHolder( + supervisor.host.clone(), + ReadToken { + account: address, + mode: state, + }, + ), + ); + + let code_slot = child_storage + .check_major_and_resolve_code_slot() + .await + .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?; + let vm_data = Box::new(SingleVMData { depth: self.context.data.depth + 1, // Permission model: doc/website/src/spec/03-vm/05-permissions.rst @@ -738,14 +755,18 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { can_write_storage: false, can_spawn_nondet: my_conf.can_spawn_nondet, can_call_others: my_conf.can_call_others, - // A `CallContract` child is read-only (static): it cannot - // write storage, send messages, or emit events. Emissions - // from the child are discarded, so allowing them would - // charge fees for effects that never surface. can_send_messages: false, can_register_runners: my_conf.can_register_runners, state_mode: state, - code_slot: crate::SlotID::ZERO, + topmost_runner_id: runners::Id::Chain { + address, + on: if state == public_abi::StorageType::LatestFinal { + runners::ChainState::Finalized + } else { + runners::ChainState::Accepted + }, + slot: code_slot, + }, }, message_data: ExtendedMessage { message: genlayer_sdk::abi::entry::MessageData { @@ -762,17 +783,7 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { entry_data: my_data.entry_data, entry_stage_data: default_entry_stage_data(), }, - storage: rt::vm::storage::Storage::new( - address, - supervisor.get_storage_limiter(), - StorageHostHolder( - supervisor.host.clone(), - ReadToken { - account: address, - mode: state, - }, - ), - ), + storage: child_storage, supervisor: supervisor.clone(), accumulator: VMDataAccumulator { data_fees_limit: self.context.data.accumulator.data_fees_limit.clone(), @@ -1657,22 +1668,19 @@ impl ContextVFS<'_> { let supervisor = self.context.data.supervisor.clone(); let is_det = self.context.data.conf.is_deterministic; let limiter = supervisor.limiter.get(is_det); - let contract_address = self.context.data.message_data.message.contract_address; - let state = crate::runners::ChainState::for_vm( - self.context.data.message_data.message.is_init, - self.context.data.conf.state_mode, - ); - let code_slot = self.context.data.conf.code_slot; + let topmost_runner_id = self.context.data.conf.topmost_runner_id.clone(); let available_custom = self.context.data.accumulator.custom_runners.clone(); + let runner = + rt::supervisor::actions::resolve_runner_id(&supervisor, &topmost_runner_id, &runner) + .await + .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?; + rt::supervisor::actions::map_runner_file( &supervisor, self.preview1, limiter, - contract_address, - state, - code_slot, - &runner, + runner, &path_in_runner, &path_in_vfs, &available_custom, @@ -1845,7 +1853,7 @@ impl ContextVFS<'_> { can_send_messages: false, can_register_runners: false, state_mode: public_abi::StorageType::Default, - code_slot: crate::SlotID::ZERO, + topmost_runner_id: self.context.data.conf.topmost_runner_id.clone(), }, message_data, supervisor: supervisor.clone(), @@ -1939,7 +1947,7 @@ impl ContextVFS<'_> { can_send_messages: zelf_conf.can_send_messages & allow_send_messages, can_register_runners: zelf_conf.can_register_runners & allow_register_runners, state_mode: zelf_conf.state_mode, - code_slot: crate::SlotID::ZERO, + topmost_runner_id: self.context.data.conf.topmost_runner_id.clone(), }, message_data, supervisor: supervisor.clone(), diff --git a/executor/src/wasi/mod.rs b/executor/src/wasi/mod.rs index ff5338f1e..2bbee2ed2 100644 --- a/executor/src/wasi/mod.rs +++ b/executor/src/wasi/mod.rs @@ -39,7 +39,11 @@ impl Context { }; Ok(Self { vfs, - preview1: preview1::Context::new(data.message_data.message.datetime, data.conf, seed), + preview1: preview1::Context::new( + data.message_data.message.datetime, + data.conf.clone(), + seed, + ), genlayer_sdk: genlayer_sdk::Context::new(data), }) } diff --git a/modules/implementation/Cargo.lock b/modules/implementation/Cargo.lock index cd8d58dc0..6838e6a7d 100644 --- a/modules/implementation/Cargo.lock +++ b/modules/implementation/Cargo.lock @@ -1031,6 +1031,7 @@ dependencies = [ "rpds", "rustix 0.38.44", "serde", + "serde_bytes", "serde_json", "serde_yaml", "symbol_table", diff --git a/tests/cases/stable/runners/sandbox_custom_runner.0.stdout b/tests/cases/stable/runners/sandbox_custom_runner.0.stdout new file mode 100644 index 000000000..d7a30c4e7 --- /dev/null +++ b/tests/cases/stable/runners/sandbox_custom_runner.0.stdout @@ -0,0 +1,3 @@ +custom runner ran +sandbox -> Return(calldata=42) +executed with `Return(null)` diff --git a/tests/cases/stable/runners/sandbox_custom_runner.jsonnet b/tests/cases/stable/runners/sandbox_custom_runner.jsonnet new file mode 100644 index 000000000..579b652bd --- /dev/null +++ b/tests/cases/stable/runners/sandbox_custom_runner.jsonnet @@ -0,0 +1,3 @@ +local simple = import 'templates/simple_deploy.jsonnet'; +local util = import 'templates/util.jsonnet'; +{entry: util.addPaths([simple.run('${jsonnetDir}/${fileBaseName}.py') {stable_hash: false, permissions: 'rwscnu'}])} diff --git a/tests/cases/stable/runners/sandbox_custom_runner.py b/tests/cases/stable/runners/sandbox_custom_runner.py new file mode 100644 index 000000000..39f33bd7b --- /dev/null +++ b/tests/cases/stable/runners/sandbox_custom_runner.py @@ -0,0 +1,13 @@ +# { "Depends": "py-genlayer:test" } +import genlayer as gl +from genlayer.vm import register_runner + + +class Contract(gl.contract.Contract): + def __init__(self): + # a custom runner whose module prints a marker when it is loaded + code = b'# { "Depends": "py-genlayer:test" }\nprint("custom runner ran")\n' + rid = register_runner(code) + # run a sandbox that loads the custom runner instead of this contract + res = gl.vm.spawn_sandbox(lambda: 42, runner=rid) + print('sandbox ->', res) From 189168341f7e33e9167c26e860a21f7565c497f5 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Wed, 24 Jun 2026 23:40:05 +0900 Subject: [PATCH 117/124] =?UTF-8?q?feat(runners):=20let=20spawn=5Fsandbox?= =?UTF-8?q?=20run=20an=20explicit=20runner=20id=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a mandatory `runner` field to the `Sandbox` gl_call. The sandbox VM now resolves it relative to the caller and loads it as its `topmost_runner_id` instead of always reusing the contract's own code: `contract` (the python default) keeps the current behavior, while a `custom:`/`name:hash`/`chain:` id runs that runner instead. Python `spawn_sandbox(runner=...)` defaults to `contract`. The integration test registers a custom runner and runs it inside a sandbox: the runner maps its own code to /contract.py, prints a marker proving it ran, then execs the bootloader to handle the sandbox entry (which returns the lambda's result). --- executor/crates/sdk-rs/src/abi/gl_call.rs | 2 ++ executor/src/wasi/genlayer_sdk.rs | 11 +++++++- .../src/genlayer/vm/__init__.py | 3 +++ runners/support/versions/current.nix | 6 ++--- .../stable/runners/sandbox_custom_runner.py | 27 ++++++++++++++++--- 5 files changed, 41 insertions(+), 8 deletions(-) diff --git a/executor/crates/sdk-rs/src/abi/gl_call.rs b/executor/crates/sdk-rs/src/abi/gl_call.rs index c41c52f86..78d571ca2 100644 --- a/executor/crates/sdk-rs/src/abi/gl_call.rs +++ b/executor/crates/sdk-rs/src/abi/gl_call.rs @@ -569,6 +569,8 @@ pub enum Message { #[cfg_attr(feature = "arbitrary", arbitrary(with = crate::abi::arb::arb_bytes))] data: Bytes, + runner: String, + allow_write_storage: bool, allow_send_messages: bool, allow_register_runners: bool, diff --git a/executor/src/wasi/genlayer_sdk.rs b/executor/src/wasi/genlayer_sdk.rs index 972622832..482be4c86 100644 --- a/executor/src/wasi/genlayer_sdk.rs +++ b/executor/src/wasi/genlayer_sdk.rs @@ -1344,12 +1344,14 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { } => self.run_nondet(data_leader, data_validator).await, gl_call::Message::Sandbox { data, + runner, allow_write_storage, allow_send_messages, allow_register_runners, } => { self.sandbox( data, + runner, allow_write_storage, allow_send_messages, allow_register_runners, @@ -1905,12 +1907,19 @@ impl ContextVFS<'_> { async fn sandbox( &mut self, data: bytes::Bytes, + runner: String, allow_write_storage: bool, allow_send_messages: bool, allow_register_runners: bool, ) -> Result { let supervisor = self.context.data.supervisor.clone(); + let parent_runner_id = self.context.data.conf.topmost_runner_id.clone(); + let topmost_runner_id = + rt::supervisor::actions::resolve_runner_id(&supervisor, &parent_runner_id, &runner) + .await + .map_err(|e| generated::types::Error::trap(crate::anyhow_to_wasmtime(e)))?; + let message_data = self .context .data @@ -1947,7 +1956,7 @@ impl ContextVFS<'_> { can_send_messages: zelf_conf.can_send_messages & allow_send_messages, can_register_runners: zelf_conf.can_register_runners & allow_register_runners, state_mode: zelf_conf.state_mode, - topmost_runner_id: self.context.data.conf.topmost_runner_id.clone(), + topmost_runner_id, }, message_data, supervisor: supervisor.clone(), diff --git a/runners/genlayer-py-std/src/genlayer/vm/__init__.py b/runners/genlayer-py-std/src/genlayer/vm/__init__.py index 8ea1805f1..12d888734 100644 --- a/runners/genlayer-py-std/src/genlayer/vm/__init__.py +++ b/runners/genlayer-py-std/src/genlayer/vm/__init__.py @@ -160,6 +160,7 @@ def _decode_sub_vm_result( def spawn_sandbox[T: calldata.Decoded]( fn: typing.Callable[[], T], *, + runner: str = 'contract', allow_write_storage: bool = False, allow_send_messages: bool = False, allow_register_runners: bool = False, @@ -175,6 +176,7 @@ def spawn_sandbox[T: calldata.Decoded]( only if the current VM holds it as well. :param fn: Function to execute in the sandbox (must be serializable with cloudpickle) + :param runner: runner id the sandbox loads instead of this contract's code; ``contract`` (default) reuses this contract's runner, a ``custom:``/``name:hash``/``chain:`` id runs that runner :param allow_write_storage: Whether to allow storage writes in the sandbox :param allow_send_messages: Whether to allow sending messages in the sandbox :param allow_register_runners: Whether to allow registering runners in the sandbox @@ -189,6 +191,7 @@ def spawn_sandbox[T: calldata.Decoded]( { 'Sandbox': { 'data': cloudpickle.dumps(fn), + 'runner': runner, 'allow_write_storage': allow_write_storage, 'allow_send_messages': allow_send_messages, 'allow_register_runners': allow_register_runners, diff --git a/runners/support/versions/current.nix b/runners/support/versions/current.nix index 67e8edc18..8c382675f 100644 --- a/runners/support/versions/current.nix +++ b/runners/support/versions/current.nix @@ -32,7 +32,7 @@ let }; genlayer-std = { - hash = "sha256-YSkNZ3Q4V5YKvIahsccz/vrmMKzGHCudWmVqZKZsHMk="; + hash = "sha256-/pdXFMD6CtosS0LH2fJbZkJg5E3sMFnpWrC3yXVONgQ="; }; genlayer-embeddings = { @@ -60,7 +60,7 @@ let wrappers = { __prefix = ""; py-genlayer = { - hash = "sha256-iUpzX4Xn1v4Ae+PDifOPNX1H2PFdMWBJCwffCclHgsk="; + hash = "sha256-u9lPFVpXuye3z8SsOfjIwRzAKfRAPy4tmTUnA+um6K0="; depends = [ cpython pyLibs.cloudpickle @@ -68,7 +68,7 @@ let ]; }; py-genlayer-multi = { - hash = "sha256-UeVY7iVg4XkC8bEsxYXJEPj/fo8Med66a+kK63uIhEM="; + hash = "sha256-woB2R5aziFLNpKCjEquWAsorIPH4/EpaRdVVYJYSy3w="; depends = [ cpython pyLibs.cloudpickle diff --git a/tests/cases/stable/runners/sandbox_custom_runner.py b/tests/cases/stable/runners/sandbox_custom_runner.py index 39f33bd7b..b2e596f1a 100644 --- a/tests/cases/stable/runners/sandbox_custom_runner.py +++ b/tests/cases/stable/runners/sandbox_custom_runner.py @@ -2,12 +2,31 @@ import genlayer as gl from genlayer.vm import register_runner +import json + class Contract(gl.contract.Contract): def __init__(self): - # a custom runner whose module prints a marker when it is loaded - code = b'# { "Depends": "py-genlayer:test" }\nprint("custom runner ran")\n' - rid = register_runner(code) - # run a sandbox that loads the custom runner instead of this contract + runner = { + 'Seq': [ + { + 'With': { + 'action': {'MapFile': {'file': 'file', 'to': '/contract.py'}}, + 'runner': 'contract', + } + }, + {'SetArgs': ['py', '-u', '-B', '/contract.py']}, + {'Depends': 'py-lib-cloudpickle:test'}, + {'Depends': 'py-lib-genlayer-std:test'}, + {'Depends': 'cpython:test'}, + ] + } + runner_dumped = json.dumps(runner) + code = ( + f'# {runner_dumped}\n' + 'print("custom runner ran")\n' + "exec(open('/py/libs/_genlayer_bootloader.py').read())\n" + ) + rid = register_runner(code.encode('utf-8')) res = gl.vm.spawn_sandbox(lambda: 42, runner=rid) print('sandbox ->', res) From 5b04cadd461555909dcf86f383dc3c2c1e607cd6 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Wed, 24 Jun 2026 23:47:58 +0900 Subject: [PATCH 118/124] =?UTF-8?q?test(balances):=20exercise=20the=20self?= =?UTF-8?q?-view=20after=20deploy,=20not=20in=20=5F=5Finit=5F=5F=20?= =?UTF-8?q?=E2=9C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit balance/balance_eth did a self-`CallContract` (`get_at(self).view().nested()`) in `__init__`, which now correctly fails: a contract's code is not visible as an on-chain runner mid-deploy. Move the body into a `main()` write method (empty `__init__`) and turn both cases into deploy-then-call, so the self-view runs once the code is committed. --- tests/cases/stable/py/balances/balance.0.stdout | 9 --------- tests/cases/stable/py/balances/balance.0_0.stdout | 10 ++++++++++ tests/cases/stable/py/balances/balance.jsonnet | 8 +++++--- tests/cases/stable/py/balances/balance.py | 4 ++++ tests/cases/stable/py/balances/balance_eth.0.stdout | 9 --------- tests/cases/stable/py/balances/balance_eth.0_0.stdout | 10 ++++++++++ tests/cases/stable/py/balances/balance_eth.jsonnet | 8 +++++--- tests/cases/stable/py/balances/balance_eth.py | 4 ++++ 8 files changed, 38 insertions(+), 24 deletions(-) create mode 100644 tests/cases/stable/py/balances/balance.0_0.stdout create mode 100644 tests/cases/stable/py/balances/balance_eth.0_0.stdout diff --git a/tests/cases/stable/py/balances/balance.0.stdout b/tests/cases/stable/py/balances/balance.0.stdout index a48130284..7d73027c8 100644 --- a/tests/cases/stable/py/balances/balance.0.stdout +++ b/tests/cases/stable/py/balances/balance.0.stdout @@ -1,10 +1 @@ -main self 10 -main At(self) 10 -=== transfer === -main self 5 -main At(self) 10 -=== call .view() === -nested self 10 -nested At(self) 10 executed with `Return(null)` -{"address":addr#0200000000000000000000000000000000000000,"call_key":b#0000000000000000000000000000000000000000000000000000000000000000,"calldata":{},"fee_params":{"execution_budget_per_round":1024,"leader_timeunits_allocation":5,"max_price_gen_per_time_unit":1606938044258990275541962092341162602522202993782792835301376,"receipt_fee_max_gas_price":20,"rotations":[4,4,4,4,4],"storage_fee_max_gas_price":20,"validator_timeunits_allocation":5},"message_fee":34836,"on":"finalized","receipt_fee":225,"subtree":b#00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000,"type":"PostMessage","value":5} diff --git a/tests/cases/stable/py/balances/balance.0_0.stdout b/tests/cases/stable/py/balances/balance.0_0.stdout new file mode 100644 index 000000000..a48130284 --- /dev/null +++ b/tests/cases/stable/py/balances/balance.0_0.stdout @@ -0,0 +1,10 @@ +main self 10 +main At(self) 10 +=== transfer === +main self 5 +main At(self) 10 +=== call .view() === +nested self 10 +nested At(self) 10 +executed with `Return(null)` +{"address":addr#0200000000000000000000000000000000000000,"call_key":b#0000000000000000000000000000000000000000000000000000000000000000,"calldata":{},"fee_params":{"execution_budget_per_round":1024,"leader_timeunits_allocation":5,"max_price_gen_per_time_unit":1606938044258990275541962092341162602522202993782792835301376,"receipt_fee_max_gas_price":20,"rotations":[4,4,4,4,4],"storage_fee_max_gas_price":20,"validator_timeunits_allocation":5},"message_fee":34836,"on":"finalized","receipt_fee":225,"subtree":b#00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000,"type":"PostMessage","value":5} diff --git a/tests/cases/stable/py/balances/balance.jsonnet b/tests/cases/stable/py/balances/balance.jsonnet index b07b7467b..84b882d8a 100644 --- a/tests/cases/stable/py/balances/balance.jsonnet +++ b/tests/cases/stable/py/balances/balance.jsonnet @@ -1,7 +1,9 @@ -local simple_deploy = import 'templates/simple_deploy.jsonnet'; +local deploy_then = import 'templates/simple_deploy_then_write.jsonnet'; local util = import 'templates/util.jsonnet'; -{entry: util.addPaths([simple_deploy.run('${jsonnetDir}/${fileBaseName}.py') { +local bal = { "balances": { "AQAAAAAAAAAAAAAAAAAAAAAAAAA=": 10, }, -}])} +}; +local base = deploy_then.run('${jsonnetDir}/${fileBaseName}.py', 'main'); +{entry: util.addPaths([base + bal + {next: [base.next[0] + bal]}])} diff --git a/tests/cases/stable/py/balances/balance.py b/tests/cases/stable/py/balances/balance.py index 323af2023..f34d2b82f 100644 --- a/tests/cases/stable/py/balances/balance.py +++ b/tests/cases/stable/py/balances/balance.py @@ -5,6 +5,10 @@ class Contract(gl.contract.Contract): def __init__(self): + pass + + @gl.public.write + def main(self): print('main self', self.balance) print('main At(self)', gl.contract.get_at(gl.message.contract_address).balance) print('=== transfer ===') diff --git a/tests/cases/stable/py/balances/balance_eth.0.stdout b/tests/cases/stable/py/balances/balance_eth.0.stdout index 6b3dd3ddd..7d73027c8 100644 --- a/tests/cases/stable/py/balances/balance_eth.0.stdout +++ b/tests/cases/stable/py/balances/balance_eth.0.stdout @@ -1,10 +1 @@ -main self 10 -main At(self) 10 -=== transfer === -main self 5 -main At(self) 10 -=== call .view() === -nested self 10 -nested At(self) 10 executed with `Return(null)` -{"address":addr#0200000000000000000000000000000000000000,"calldata":b#,"fee_params":{"gas_limit":1606938044258990275541962092341162602522202993782792835301376,"max_gas_price":0},"message_fee":0,"receipt_fee":129,"type":"EthSend","value":5} diff --git a/tests/cases/stable/py/balances/balance_eth.0_0.stdout b/tests/cases/stable/py/balances/balance_eth.0_0.stdout new file mode 100644 index 000000000..6b3dd3ddd --- /dev/null +++ b/tests/cases/stable/py/balances/balance_eth.0_0.stdout @@ -0,0 +1,10 @@ +main self 10 +main At(self) 10 +=== transfer === +main self 5 +main At(self) 10 +=== call .view() === +nested self 10 +nested At(self) 10 +executed with `Return(null)` +{"address":addr#0200000000000000000000000000000000000000,"calldata":b#,"fee_params":{"gas_limit":1606938044258990275541962092341162602522202993782792835301376,"max_gas_price":0},"message_fee":0,"receipt_fee":129,"type":"EthSend","value":5} diff --git a/tests/cases/stable/py/balances/balance_eth.jsonnet b/tests/cases/stable/py/balances/balance_eth.jsonnet index 78bab86a7..aa06f369c 100644 --- a/tests/cases/stable/py/balances/balance_eth.jsonnet +++ b/tests/cases/stable/py/balances/balance_eth.jsonnet @@ -1,7 +1,9 @@ -local simple_deploy = import 'templates/simple_deploy.jsonnet'; +local deploy_then = import 'templates/simple_deploy_then_write.jsonnet'; local util = import 'templates/util.jsonnet'; -{entry: util.addPaths([simple_deploy.run('${jsonnetDir}/balance_eth.py') { +local bal = { "balances": { "AQAAAAAAAAAAAAAAAAAAAAAAAAA=": 10, }, -}])} +}; +local base = deploy_then.run('${jsonnetDir}/balance_eth.py', 'main'); +{entry: util.addPaths([base + bal + {next: [base.next[0] + bal]}])} diff --git a/tests/cases/stable/py/balances/balance_eth.py b/tests/cases/stable/py/balances/balance_eth.py index e7803e6b0..f158ff104 100644 --- a/tests/cases/stable/py/balances/balance_eth.py +++ b/tests/cases/stable/py/balances/balance_eth.py @@ -14,6 +14,10 @@ class Write: class Contract(gl.contract.Contract): def __init__(self): + pass + + @gl.public.write + def main(self): print('main self', self.balance) print('main At(self)', EthContract(gl.message.contract_address).balance) print('=== transfer ===') From 5761659bfa393a55cc7f57c92bca96eb95d213ac Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Wed, 24 Jun 2026 23:56:33 +0900 Subject: [PATCH 119/124] =?UTF-8?q?test(runners):=20split=20major-mismatch?= =?UTF-8?q?=20into=20per-entry-point=20checks=20=E2=9C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the single major_mismatch case with a major-mismatch/ subdir that exercises every place a stale contract major is read: - top_level: a top-level call to a contract whose stored major != node major (the run_with_impl code-slot resolution check) - call: a CallContract into such a contract - map_file: a `chain:` runner map_file pointing at such a contract (the get_arch chain-load check) The target contract persists major=5 in its own storage during deploy, so no host/manager lying is needed; the deploy succeeds and every later read of its runner is rejected with `invalid_contract major_mismatch`. --- .../stable/runners/major-mismatch/call.0.stdout | 2 ++ .../call.0_0.stdout} | 1 - .../call.0_0_0.stdout} | 0 .../stable/runners/major-mismatch/call.jsonnet | 10 ++++++++++ .../stable/runners/major-mismatch/caller.py | 16 ++++++++++++++++ .../runners/major-mismatch/map_file.0.stdout | 2 ++ .../runners/major-mismatch/map_file.0_0.stdout | 1 + .../major-mismatch/map_file.0_0_0.stdout | 1 + .../runners/major-mismatch/map_file.jsonnet | 10 ++++++++++ .../stable/runners/major-mismatch/target.py | 17 +++++++++++++++++ .../runners/major-mismatch/top_level.0.stdout | 2 ++ .../runners/major-mismatch/top_level.0_0.stdout | 1 + .../top_level.jsonnet} | 2 +- tests/cases/stable/runners/major_mismatch.py | 15 --------------- 14 files changed, 63 insertions(+), 17 deletions(-) create mode 100644 tests/cases/stable/runners/major-mismatch/call.0.stdout rename tests/cases/stable/runners/{major_mismatch.0.stdout => major-mismatch/call.0_0.stdout} (76%) rename tests/cases/stable/runners/{major_mismatch.0_0.stdout => major-mismatch/call.0_0_0.stdout} (100%) create mode 100644 tests/cases/stable/runners/major-mismatch/call.jsonnet create mode 100644 tests/cases/stable/runners/major-mismatch/caller.py create mode 100644 tests/cases/stable/runners/major-mismatch/map_file.0.stdout create mode 100644 tests/cases/stable/runners/major-mismatch/map_file.0_0.stdout create mode 100644 tests/cases/stable/runners/major-mismatch/map_file.0_0_0.stdout create mode 100644 tests/cases/stable/runners/major-mismatch/map_file.jsonnet create mode 100644 tests/cases/stable/runners/major-mismatch/target.py create mode 100644 tests/cases/stable/runners/major-mismatch/top_level.0.stdout create mode 100644 tests/cases/stable/runners/major-mismatch/top_level.0_0.stdout rename tests/cases/stable/runners/{major_mismatch.jsonnet => major-mismatch/top_level.jsonnet} (89%) delete mode 100644 tests/cases/stable/runners/major_mismatch.py diff --git a/tests/cases/stable/runners/major-mismatch/call.0.stdout b/tests/cases/stable/runners/major-mismatch/call.0.stdout new file mode 100644 index 000000000..8dbb414b5 --- /dev/null +++ b/tests/cases/stable/runners/major-mismatch/call.0.stdout @@ -0,0 +1,2 @@ +deployed target with major 5 +executed with `Return(null)` diff --git a/tests/cases/stable/runners/major_mismatch.0.stdout b/tests/cases/stable/runners/major-mismatch/call.0_0.stdout similarity index 76% rename from tests/cases/stable/runners/major_mismatch.0.stdout rename to tests/cases/stable/runners/major-mismatch/call.0_0.stdout index ae5576e85..7d73027c8 100644 --- a/tests/cases/stable/runners/major_mismatch.0.stdout +++ b/tests/cases/stable/runners/major-mismatch/call.0_0.stdout @@ -1,2 +1 @@ -deployed executed with `Return(null)` diff --git a/tests/cases/stable/runners/major_mismatch.0_0.stdout b/tests/cases/stable/runners/major-mismatch/call.0_0_0.stdout similarity index 100% rename from tests/cases/stable/runners/major_mismatch.0_0.stdout rename to tests/cases/stable/runners/major-mismatch/call.0_0_0.stdout diff --git a/tests/cases/stable/runners/major-mismatch/call.jsonnet b/tests/cases/stable/runners/major-mismatch/call.jsonnet new file mode 100644 index 000000000..ac43f21eb --- /dev/null +++ b/tests/cases/stable/runners/major-mismatch/call.jsonnet @@ -0,0 +1,10 @@ +local two = import 'templates/two.jsonnet'; +local util = import 'templates/util.jsonnet'; +{entry: util.addPaths([two.run('${jsonnetDir}/caller.py', '${jsonnetDir}/target.py', + ||| + { + "method": "call", + "args": [Address(toAddr)] + } + ||| +)])} diff --git a/tests/cases/stable/runners/major-mismatch/caller.py b/tests/cases/stable/runners/major-mismatch/caller.py new file mode 100644 index 000000000..18c97c9cc --- /dev/null +++ b/tests/cases/stable/runners/major-mismatch/caller.py @@ -0,0 +1,16 @@ +# { "Depends": "py-genlayer:test" } +import genlayer as gl +from genlayer.types import * + + +class Contract(gl.contract.Contract): + def __init__(self): + pass + + @gl.public.write + def call(self, addr: Address): + gl.contract.get_at(addr).view().foo() + + @gl.public.write + def map(self, addr: Address): + gl.vm.map_file(f'chain:{addr.as_hex}:a', 'file', '/mapped.txt') diff --git a/tests/cases/stable/runners/major-mismatch/map_file.0.stdout b/tests/cases/stable/runners/major-mismatch/map_file.0.stdout new file mode 100644 index 000000000..8dbb414b5 --- /dev/null +++ b/tests/cases/stable/runners/major-mismatch/map_file.0.stdout @@ -0,0 +1,2 @@ +deployed target with major 5 +executed with `Return(null)` diff --git a/tests/cases/stable/runners/major-mismatch/map_file.0_0.stdout b/tests/cases/stable/runners/major-mismatch/map_file.0_0.stdout new file mode 100644 index 000000000..7d73027c8 --- /dev/null +++ b/tests/cases/stable/runners/major-mismatch/map_file.0_0.stdout @@ -0,0 +1 @@ +executed with `Return(null)` diff --git a/tests/cases/stable/runners/major-mismatch/map_file.0_0_0.stdout b/tests/cases/stable/runners/major-mismatch/map_file.0_0_0.stdout new file mode 100644 index 000000000..f70cfaea6 --- /dev/null +++ b/tests/cases/stable/runners/major-mismatch/map_file.0_0_0.stdout @@ -0,0 +1 @@ +executed with `VMError("invalid_contract major_mismatch")` diff --git a/tests/cases/stable/runners/major-mismatch/map_file.jsonnet b/tests/cases/stable/runners/major-mismatch/map_file.jsonnet new file mode 100644 index 000000000..e8dfbc844 --- /dev/null +++ b/tests/cases/stable/runners/major-mismatch/map_file.jsonnet @@ -0,0 +1,10 @@ +local two = import 'templates/two.jsonnet'; +local util = import 'templates/util.jsonnet'; +{entry: util.addPaths([two.run('${jsonnetDir}/caller.py', '${jsonnetDir}/target.py', + ||| + { + "method": "map", + "args": [Address(toAddr)] + } + ||| +)])} diff --git a/tests/cases/stable/runners/major-mismatch/target.py b/tests/cases/stable/runners/major-mismatch/target.py new file mode 100644 index 000000000..95471e283 --- /dev/null +++ b/tests/cases/stable/runners/major-mismatch/target.py @@ -0,0 +1,17 @@ +# { "Depends": "py-genlayer:test" } +import genlayer as gl +from genlayer.storage.root import Root + + +class Contract(gl.contract.Contract): + def __init__(self): + # persist a major that does not match the node's, so every later read of + # this contract's runner (top-level call, CallContract, map_file) is + # rejected before it runs + Root.get().major = 5 + print('deployed target with major 5') + + @gl.public.view + def foo(self) -> int: + print('should not be reached') + return 1 diff --git a/tests/cases/stable/runners/major-mismatch/top_level.0.stdout b/tests/cases/stable/runners/major-mismatch/top_level.0.stdout new file mode 100644 index 000000000..8dbb414b5 --- /dev/null +++ b/tests/cases/stable/runners/major-mismatch/top_level.0.stdout @@ -0,0 +1,2 @@ +deployed target with major 5 +executed with `Return(null)` diff --git a/tests/cases/stable/runners/major-mismatch/top_level.0_0.stdout b/tests/cases/stable/runners/major-mismatch/top_level.0_0.stdout new file mode 100644 index 000000000..f70cfaea6 --- /dev/null +++ b/tests/cases/stable/runners/major-mismatch/top_level.0_0.stdout @@ -0,0 +1 @@ +executed with `VMError("invalid_contract major_mismatch")` diff --git a/tests/cases/stable/runners/major_mismatch.jsonnet b/tests/cases/stable/runners/major-mismatch/top_level.jsonnet similarity index 89% rename from tests/cases/stable/runners/major_mismatch.jsonnet rename to tests/cases/stable/runners/major-mismatch/top_level.jsonnet index 87bd4275b..da403f0a2 100644 --- a/tests/cases/stable/runners/major_mismatch.jsonnet +++ b/tests/cases/stable/runners/major-mismatch/top_level.jsonnet @@ -3,7 +3,7 @@ local util = import 'templates/util.jsonnet'; { entry: util.addPaths([{ vars: {}, - code: '${jsonnetDir}/major_mismatch.py', + code: '${jsonnetDir}/target.py', message: msg + {is_init: true}, calldata: '{}', stable_hash: false, diff --git a/tests/cases/stable/runners/major_mismatch.py b/tests/cases/stable/runners/major_mismatch.py deleted file mode 100644 index 9b119bf82..000000000 --- a/tests/cases/stable/runners/major_mismatch.py +++ /dev/null @@ -1,15 +0,0 @@ -# { "Depends": "py-genlayer:test" } -import genlayer as gl -from genlayer.storage.root import Root - - -class Contract(gl.contract.Contract): - def __init__(self): - # write a major that does not match the node's, so the *next* invocation - # is rejected before it runs - Root.get().major = 5 - print('deployed') - - @gl.public.write - def foo(self) -> None: - print('should not be reached') From 4bb5387d2de504b8f14dfa8c686f60063e1efca0 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Wed, 24 Jun 2026 23:59:03 +0900 Subject: [PATCH 120/124] =?UTF-8?q?test(runners):=20merge=20major-mismatch?= =?UTF-8?q?=20checks=20into=20one=20jsonnet=20=E2=9C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Collapse the three per-entry-point jsonnets into a single major_mismatch.jsonnet with three indexed entries (top-level call / CallContract / map_file), sharing target.py and caller.py. `util.mapGraph` stamps `stable_hash: false` across every step. Same coverage, far fewer files. --- .../runners/major-mismatch/call.jsonnet | 10 ----- ...{call.0.stdout => major_mismatch.0.stdout} | 0 ...0_0_0.stdout => major_mismatch.0_0.stdout} | 0 ..._file.0.stdout => major_mismatch.1.stdout} | 0 ...l.0_0.stdout => major_mismatch.1_0.stdout} | 0 ...0_0.stdout => major_mismatch.1_0_0.stdout} | 0 ...level.0.stdout => major_mismatch.2.stdout} | 0 ...e.0_0.stdout => major_mismatch.2_0.stdout} | 0 ...0_0.stdout => major_mismatch.2_0_0.stdout} | 0 .../major-mismatch/major_mismatch.jsonnet | 40 +++++++++++++++++++ .../runners/major-mismatch/map_file.jsonnet | 10 ----- .../runners/major-mismatch/top_level.jsonnet | 18 --------- 12 files changed, 40 insertions(+), 38 deletions(-) delete mode 100644 tests/cases/stable/runners/major-mismatch/call.jsonnet rename tests/cases/stable/runners/major-mismatch/{call.0.stdout => major_mismatch.0.stdout} (100%) rename tests/cases/stable/runners/major-mismatch/{call.0_0_0.stdout => major_mismatch.0_0.stdout} (100%) rename tests/cases/stable/runners/major-mismatch/{map_file.0.stdout => major_mismatch.1.stdout} (100%) rename tests/cases/stable/runners/major-mismatch/{call.0_0.stdout => major_mismatch.1_0.stdout} (100%) rename tests/cases/stable/runners/major-mismatch/{map_file.0_0_0.stdout => major_mismatch.1_0_0.stdout} (100%) rename tests/cases/stable/runners/major-mismatch/{top_level.0.stdout => major_mismatch.2.stdout} (100%) rename tests/cases/stable/runners/major-mismatch/{map_file.0_0.stdout => major_mismatch.2_0.stdout} (100%) rename tests/cases/stable/runners/major-mismatch/{top_level.0_0.stdout => major_mismatch.2_0_0.stdout} (100%) create mode 100644 tests/cases/stable/runners/major-mismatch/major_mismatch.jsonnet delete mode 100644 tests/cases/stable/runners/major-mismatch/map_file.jsonnet delete mode 100644 tests/cases/stable/runners/major-mismatch/top_level.jsonnet diff --git a/tests/cases/stable/runners/major-mismatch/call.jsonnet b/tests/cases/stable/runners/major-mismatch/call.jsonnet deleted file mode 100644 index ac43f21eb..000000000 --- a/tests/cases/stable/runners/major-mismatch/call.jsonnet +++ /dev/null @@ -1,10 +0,0 @@ -local two = import 'templates/two.jsonnet'; -local util = import 'templates/util.jsonnet'; -{entry: util.addPaths([two.run('${jsonnetDir}/caller.py', '${jsonnetDir}/target.py', - ||| - { - "method": "call", - "args": [Address(toAddr)] - } - ||| -)])} diff --git a/tests/cases/stable/runners/major-mismatch/call.0.stdout b/tests/cases/stable/runners/major-mismatch/major_mismatch.0.stdout similarity index 100% rename from tests/cases/stable/runners/major-mismatch/call.0.stdout rename to tests/cases/stable/runners/major-mismatch/major_mismatch.0.stdout diff --git a/tests/cases/stable/runners/major-mismatch/call.0_0_0.stdout b/tests/cases/stable/runners/major-mismatch/major_mismatch.0_0.stdout similarity index 100% rename from tests/cases/stable/runners/major-mismatch/call.0_0_0.stdout rename to tests/cases/stable/runners/major-mismatch/major_mismatch.0_0.stdout diff --git a/tests/cases/stable/runners/major-mismatch/map_file.0.stdout b/tests/cases/stable/runners/major-mismatch/major_mismatch.1.stdout similarity index 100% rename from tests/cases/stable/runners/major-mismatch/map_file.0.stdout rename to tests/cases/stable/runners/major-mismatch/major_mismatch.1.stdout diff --git a/tests/cases/stable/runners/major-mismatch/call.0_0.stdout b/tests/cases/stable/runners/major-mismatch/major_mismatch.1_0.stdout similarity index 100% rename from tests/cases/stable/runners/major-mismatch/call.0_0.stdout rename to tests/cases/stable/runners/major-mismatch/major_mismatch.1_0.stdout diff --git a/tests/cases/stable/runners/major-mismatch/map_file.0_0_0.stdout b/tests/cases/stable/runners/major-mismatch/major_mismatch.1_0_0.stdout similarity index 100% rename from tests/cases/stable/runners/major-mismatch/map_file.0_0_0.stdout rename to tests/cases/stable/runners/major-mismatch/major_mismatch.1_0_0.stdout diff --git a/tests/cases/stable/runners/major-mismatch/top_level.0.stdout b/tests/cases/stable/runners/major-mismatch/major_mismatch.2.stdout similarity index 100% rename from tests/cases/stable/runners/major-mismatch/top_level.0.stdout rename to tests/cases/stable/runners/major-mismatch/major_mismatch.2.stdout diff --git a/tests/cases/stable/runners/major-mismatch/map_file.0_0.stdout b/tests/cases/stable/runners/major-mismatch/major_mismatch.2_0.stdout similarity index 100% rename from tests/cases/stable/runners/major-mismatch/map_file.0_0.stdout rename to tests/cases/stable/runners/major-mismatch/major_mismatch.2_0.stdout diff --git a/tests/cases/stable/runners/major-mismatch/top_level.0_0.stdout b/tests/cases/stable/runners/major-mismatch/major_mismatch.2_0_0.stdout similarity index 100% rename from tests/cases/stable/runners/major-mismatch/top_level.0_0.stdout rename to tests/cases/stable/runners/major-mismatch/major_mismatch.2_0_0.stdout diff --git a/tests/cases/stable/runners/major-mismatch/major_mismatch.jsonnet b/tests/cases/stable/runners/major-mismatch/major_mismatch.jsonnet new file mode 100644 index 000000000..4c0148c2f --- /dev/null +++ b/tests/cases/stable/runners/major-mismatch/major_mismatch.jsonnet @@ -0,0 +1,40 @@ +local two = import 'templates/two.jsonnet'; +local msg = import 'templates/message.json'; +local util = import 'templates/util.jsonnet'; + +// every entry point that reads a contract's (mismatched) major must reject it: +local entries = [ + // 0: top-level call to a major-mismatched contract + { + vars: {}, + code: '${jsonnetDir}/target.py', + message: msg + {is_init: true}, + calldata: '{}', + next: [{ + vars: {}, + code: null, + message: msg, + calldata: std.manifestJsonEx({method: 'foo', args: []}, ' '), + }], + }, + // 1: CallContract into a major-mismatched contract + two.run('${jsonnetDir}/caller.py', '${jsonnetDir}/target.py', + ||| + { + "method": "call", + "args": [Address(toAddr)] + } + ||| + ), + // 2: map_file from a major-mismatched contract + two.run('${jsonnetDir}/caller.py', '${jsonnetDir}/target.py', + ||| + { + "method": "map", + "args": [Address(toAddr)] + } + ||| + ), +]; + +{entry: util.addPaths(util.mapGraph(function(e) e + {stable_hash: false}, entries))} diff --git a/tests/cases/stable/runners/major-mismatch/map_file.jsonnet b/tests/cases/stable/runners/major-mismatch/map_file.jsonnet deleted file mode 100644 index e8dfbc844..000000000 --- a/tests/cases/stable/runners/major-mismatch/map_file.jsonnet +++ /dev/null @@ -1,10 +0,0 @@ -local two = import 'templates/two.jsonnet'; -local util = import 'templates/util.jsonnet'; -{entry: util.addPaths([two.run('${jsonnetDir}/caller.py', '${jsonnetDir}/target.py', - ||| - { - "method": "map", - "args": [Address(toAddr)] - } - ||| -)])} diff --git a/tests/cases/stable/runners/major-mismatch/top_level.jsonnet b/tests/cases/stable/runners/major-mismatch/top_level.jsonnet deleted file mode 100644 index da403f0a2..000000000 --- a/tests/cases/stable/runners/major-mismatch/top_level.jsonnet +++ /dev/null @@ -1,18 +0,0 @@ -local msg = import 'templates/message.json'; -local util = import 'templates/util.jsonnet'; -{ - entry: util.addPaths([{ - vars: {}, - code: '${jsonnetDir}/target.py', - message: msg + {is_init: true}, - calldata: '{}', - stable_hash: false, - next: [{ - vars: {}, - code: null, - message: msg, - calldata: std.manifestJsonEx({method: 'foo', args: []}, ' '), - stable_hash: false, - }], - }]) -} From 2bf18cc553abebaa25e850f69d85ee2e3106eb61 Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Thu, 25 Jun 2026 00:23:27 +0900 Subject: [PATCH 121/124] =?UTF-8?q?fix(vfs):=20release=20limiter=20budget?= =?UTF-8?q?=20when=20fd=20allocation=20fails=20=F0=9F=90=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/src/wasi/vfs.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/executor/src/wasi/vfs.rs b/executor/src/wasi/vfs.rs index e28dfe2b0..ac151b042 100644 --- a/executor/src/wasi/vfs.rs +++ b/executor/src/wasi/vfs.rs @@ -149,7 +149,15 @@ impl VFS { return Err(rt::errors::VMError(abi::consts::VmError::oom().ram().val(), None).into()); } - let fd = self.alloc_fd()?; + let fd = match self.alloc_fd() { + Ok(fd) => fd, + Err(e) => { + if value.release_memory { + self.limiter.release(value.contents.len() as u32); + } + return Err(e); + } + }; self.fds.insert(fd, FileDescriptor::File(value)); Ok(fd) } From 235800945d67be7cc3e17dbdac86f597951df72e Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Thu, 25 Jun 2026 00:28:30 +0900 Subject: [PATCH 122/124] =?UTF-8?q?perf(runners):=20restore=20binary=5Fsea?= =?UTF-8?q?rch=20in=20has=5Fin=5Fall=20=E2=9A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/src/runners/cache.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/executor/src/runners/cache.rs b/executor/src/runners/cache.rs index 0e00a6235..e2b15d530 100644 --- a/executor/src/runners/cache.rs +++ b/executor/src/runners/cache.rs @@ -95,7 +95,7 @@ impl Reader { pub fn has_in_all(&self, id: &str, hash: &str) -> bool { match self.all.get(id) { - Some(hashes) => hashes.iter().any(|h| h.as_str() == hash), + Some(hashes) => hashes.binary_search_by(|h| h.as_str().cmp(hash)).is_ok(), None => false, } } From f5f099f3f7b998887ebd81fbbf11ae9b664d4fea Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Thu, 25 Jun 2026 00:28:31 +0900 Subject: [PATCH 123/124] =?UTF-8?q?test(runners):=20cover=20register=5Frun?= =?UTF-8?q?ner=20in=20nondet=20and=20runtime=20map=20into=20/vm/=20?= =?UTF-8?q?=E2=9C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../stable/runners/map_vm_runtime.0.stdout | 1 + .../stable/runners/map_vm_runtime.jsonnet | 3 +++ tests/cases/stable/runners/map_vm_runtime.py | 8 ++++++++ .../stable/runners/register_nondet.0.stdout | 2 ++ .../stable/runners/register_nondet.jsonnet | 3 +++ tests/cases/stable/runners/register_nondet.py | 18 ++++++++++++++++++ 6 files changed, 35 insertions(+) create mode 100644 tests/cases/stable/runners/map_vm_runtime.0.stdout create mode 100644 tests/cases/stable/runners/map_vm_runtime.jsonnet create mode 100644 tests/cases/stable/runners/map_vm_runtime.py create mode 100644 tests/cases/stable/runners/register_nondet.0.stdout create mode 100644 tests/cases/stable/runners/register_nondet.jsonnet create mode 100644 tests/cases/stable/runners/register_nondet.py diff --git a/tests/cases/stable/runners/map_vm_runtime.0.stdout b/tests/cases/stable/runners/map_vm_runtime.0.stdout new file mode 100644 index 000000000..3a6b81bc5 --- /dev/null +++ b/tests/cases/stable/runners/map_vm_runtime.0.stdout @@ -0,0 +1 @@ +executed with `VMError("invalid_contract malformed_runner")` diff --git a/tests/cases/stable/runners/map_vm_runtime.jsonnet b/tests/cases/stable/runners/map_vm_runtime.jsonnet new file mode 100644 index 000000000..5c0489864 --- /dev/null +++ b/tests/cases/stable/runners/map_vm_runtime.jsonnet @@ -0,0 +1,3 @@ +local simple = import 'templates/simple_deploy.jsonnet'; +local util = import 'templates/util.jsonnet'; +{entry: util.addPaths([simple.run('${jsonnetDir}/map_vm_runtime.py') {stable_hash: false}])} diff --git a/tests/cases/stable/runners/map_vm_runtime.py b/tests/cases/stable/runners/map_vm_runtime.py new file mode 100644 index 000000000..a7f7b4bab --- /dev/null +++ b/tests/cases/stable/runners/map_vm_runtime.py @@ -0,0 +1,8 @@ +# { "Depends": "py-genlayer:test" } +from genlayer.vm import map_file + +# mapping into /vm/ is forbidden; the runtime gl_call path must reject it just +# like the InitAction MapFile path does (see runners/map-vm). The rejection is a +# malformed_runner trap, so it terminates execution and is not catchable here. +map_file('contract', 'file', '/vm/evil.py') +exit(0) diff --git a/tests/cases/stable/runners/register_nondet.0.stdout b/tests/cases/stable/runners/register_nondet.0.stdout new file mode 100644 index 000000000..e26bb8a09 --- /dev/null +++ b/tests/cases/stable/runners/register_nondet.0.stdout @@ -0,0 +1,2 @@ +forbidden: SystemError +executed with `Return(null)` diff --git a/tests/cases/stable/runners/register_nondet.jsonnet b/tests/cases/stable/runners/register_nondet.jsonnet new file mode 100644 index 000000000..b744a3f9d --- /dev/null +++ b/tests/cases/stable/runners/register_nondet.jsonnet @@ -0,0 +1,3 @@ +local simple = import 'templates/simple_deploy.jsonnet'; +local util = import 'templates/util.jsonnet'; +{entry: util.addPaths([simple.run('${jsonnetDir}/register_nondet.py') {stable_hash: false, permissions: 'rwscnu'}])} diff --git a/tests/cases/stable/runners/register_nondet.py b/tests/cases/stable/runners/register_nondet.py new file mode 100644 index 000000000..3a1afbe20 --- /dev/null +++ b/tests/cases/stable/runners/register_nondet.py @@ -0,0 +1,18 @@ +# { "Depends": "py-genlayer:test" } +import genlayer as gl +from genlayer.vm import register_runner + + +class Contract(gl.contract.Contract): + def __init__(self): + def leader(): + # register_runner is deterministic-only; calling it from inside a + # nondet block must be refused even though `u` (register) is granted, + # i.e. the rejection comes from the is_deterministic gate, not perms. + try: + register_runner(b'# { "Depends": "py-genlayer:test" }\nx\n') + return 'registered (LEAK)' + except Exception as e: + return f'forbidden: {type(e).__name__}' + + print(gl.vm.run_nondet(leader, lambda r: True)) From bb04dc508dd033e14e0cea0f1a478916adb22b6e Mon Sep 17 00:00:00 2001 From: kp2pml30 Date: Thu, 25 Jun 2026 01:04:56 +0900 Subject: [PATCH 124/124] =?UTF-8?q?chore(tests):=20fix=20tests=20=E2=9C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- executor/crates/common/build.rs | 2 +- executor/fuzz/genvm-storage.rs | 10 +++--- executor/tests/runner_id.rs | 32 ++++--------------- .../lib/python/post-install/__main__.py | 32 ++++++++++--------- runners/support/views/docs.nix | 4 ++- support/ci/pipelines/test-rust.sh | 8 +++-- tests/cases/_hello_world_.0.hash | 1 + tests/cases/_hello_world_class.0.hash | 1 + tests/cases/_hello_world_class.0_0.hash | 1 + tests/cases/_hello_world_class_nondet.0.hash | 1 + .../semi-stable/llm/percent_in_prompt.0.hash | 1 + tests/cases/semi-stable/llm/woc.0.hash | 1 + tests/cases/semi-stable/llm/woc.0_0.hash | 1 + tests/cases/semi-stable/llm/woc.0_0_0_0.hash | 1 + .../web/file_schema_web_bash.0.hash | 1 + .../web/file_schema_web_proc.0.hash | 1 + .../semi-stable/web/request_signed.0.hash | 1 + .../wasi/environ_args/environ_args.0.hash | 1 + .../wasi/hash_random/hash_random.0.hash | 1 + .../agentic/wasi/set_order/set_order.0.hash | 1 + .../agentic/wasi/wasi_clock/wasi_clock.0.hash | 1 + .../wasi/wasi_random/wasi_random.0.hash | 1 + .../stable/exploits/call_wasi_extra.0.hash | 1 + tests/cases/stable/exploits/close_std.0.hash | 1 + .../stable/exploits/deep_calldata.0.hash | 1 + .../exploits/disagree_in_sandbox.0.hash | 1 + tests/cases/stable/exploits/flt.0.hash | 1 + tests/cases/stable/exploits/fork_bomb.0.hash | 1 + .../cases/stable/exploits/method_init.0.hash | 1 + .../stable/exploits/method_init.0_0.hash | 1 + .../stable/exploits/method_private.0.hash | 1 + .../stable/exploits/method_private.0_0.hash | 1 + tests/cases/stable/exploits/oom.0.hash | 1 + tests/cases/stable/exploits/rec.0.hash | 1 + tests/cases/stable/exploits/rec_1023.0.hash | 1 + tests/cases/stable/exploits/rec_1024.0.hash | 1 + .../stable/exploits/storage_page_limit.0.hash | 1 + .../exploits/storage_page_limit.0_0.hash | 1 + .../exploits/storage_page_limit.0_1.hash | 1 + .../stable/exploits/storage_rw_long.0.hash | 1 + .../stable/exploits/storage_rw_long.0_0.hash | 1 + .../subtract_on_start_underflow.0.hash | 1 + .../cases/stable/exploits/unreachable.0.hash | 1 + .../leader_errors/empty_leader_result.0.hash | 1 + .../empty_leader_result.0_0.hash | 1 + .../leader_errors/leader_no_nondet.0.hash | 1 + .../leader_errors/leader_no_nondet.0_0.hash | 1 + .../nondet/leader_errors/simple_leader.0.hash | 1 + .../leader_errors/simple_leader.0_0.hash | 1 + .../leader_errors/simple_valid_err_err.0.hash | 1 + .../simple_valid_err_err.0_0.hash | 1 + .../simple_valid_err_exit.0.hash | 1 + .../simple_valid_err_exit.0_0.hash | 1 + .../simple_valid_err_exit_wrong_err.0.hash | 1 + .../simple_valid_err_exit_wrong_err.0_0.hash | 1 + .../simple_valid_err_nerr.0.hash | 1 + .../simple_valid_err_nerr.0_0.hash | 1 + .../nondet/metod_det_get_webpage.0.hash | 1 + .../nondet/metod_det_get_webpage.0_0.hash | 1 + tests/cases/stable/nondet/trivial.0.hash | 1 + tests/cases/stable/nondet/trivial.0_0.hash | 1 + .../nondet/validator/rollback_agree.0.hash | 1 + .../nondet/validator/rollback_agree.0_0.hash | 1 + .../nondet/validator/rollback_disagree.0.hash | 1 + .../validator/rollback_disagree.0_0.hash | 1 + .../nondet/validator/rollback_imm.0.hash | 1 + .../nondet/validator/rollback_imm.0_0.hash | 1 + .../nondet/validator/rollback_imm.0_1.hash | 1 + .../nondet/validator/rollback_imm.0_2.hash | 1 + .../cases/stable/nondet/validator/sync.0.hash | 1 + .../stable/nondet/validator/sync.0_0.hash | 1 + .../stable/nondet/validator/sync_err.0.hash | 1 + .../stable/nondet/validator/sync_err.0_0.hash | 1 + tests/cases/stable/py/balances/balance.0.hash | 1 + .../cases/stable/py/balances/balance.0_0.hash | 1 + .../stable/py/balances/balance_eth.0.hash | 1 + .../stable/py/balances/balance_eth.0_0.hash | 1 + .../py/balances/sandbox_overspend.0.hash | 1 + .../py/balances/sandbox_overspend_2.0.hash | 1 + .../stable/py/balances/undefined_all.0.hash | 1 + .../stable/py/balances/undefined_all.0_0.hash | 1 + .../py/balances/undefined_all.0_0_0.hash | 1 + .../py/balances/undefined_method.0.hash | 1 + .../py/balances/undefined_method.0_0.hash | 1 + .../py/balances/undefined_method.0_0_0.hash | 1 + .../balances/undefined_method_payable.0.hash | 1 + .../undefined_method_payable.0_0.hash | 1 + .../undefined_method_payable.0_0_0.hash | 1 + .../py/balances/undefined_receive.0.hash | 1 + .../py/balances/undefined_receive.0_0.hash | 1 + .../py/balances/undefined_receive.0_0_0.hash | 1 + .../cases/stable/py/embeddings/simple.0.hash | 1 + .../stable/py/embeddings/simple.0_0.hash | 1 + .../stable/py/embeddings/simple_det.0.hash | 1 + .../stable/py/embeddings/simple_det.0_0.hash | 1 + .../py/embeddings/simple_tokenizer.0.hash | 1 + .../py/embeddings/simple_tokenizer.0_0.hash | 1 + tests/cases/stable/py/embeddings/vecdb.0.hash | 1 + .../cases/stable/py/events/post_event.0.hash | 1 + .../py/intercontract/call_self_view.0.hash | 1 + .../stable/py/intercontract/call_view.0.hash | 1 + .../py/intercontract/call_view.0_0.hash | 1 + .../py/intercontract/call_view.0_0_0.hash | 1 + .../intercontract/call_view_committed.0.hash | 1 + .../call_view_committed.0_0.hash | 1 + .../py/intercontract/call_view_emit.0.hash | 1 + .../py/intercontract/call_view_emit.0_0.hash | 1 + .../intercontract/call_view_emit.0_0_0.hash | 1 + .../py/intercontract/call_view_iface.0.hash | 1 + .../py/intercontract/call_view_iface.0_0.hash | 1 + .../intercontract/call_view_iface.0_0_0.hash | 1 + .../stable/py/intercontract/deploy.0.hash | 1 + .../py/intercontract/deploy_salt.0.hash | 1 + .../py/intercontract/eth_call_view.0.hash | 1 + .../py/intercontract/send_message.0.hash | 1 + .../py/intercontract/send_message_eth.0.hash | 1 + .../py/intercontract/send_message_on.0.hash | 1 + .../py/intercontract/send_message_on.0_0.hash | 1 + .../intercontract/send_message_on.0_0_0.hash | 1 + .../stable/py/other/meth/method_init.0.hash | 1 + .../other/meth/method_init_wrong_name.0.hash | 1 + .../stable/py/other/meth/method_public.0.hash | 1 + .../py/other/meth/method_public.0_0.hash | 1 + .../stable/py/other/meth/method_retn.0.hash | 1 + .../stable/py/other/meth/method_retn.0_0.hash | 1 + .../py/other/meth/method_retn_view.0.hash | 1 + .../py/other/meth/method_retn_view.0_0.hash | 1 + .../py/other/meth/method_rollback.0.hash | 1 + .../py/other/meth/method_rollback.0_0.hash | 1 + .../cases/stable/py/other/ret/returns.0.hash | 1 + .../stable/py/other/ret/returns.0_0.hash | 1 + .../cases/stable/py/other/ret/returns.1.hash | 1 + .../stable/py/other/ret/returns.1_0.hash | 1 + .../cases/stable/py/other/ret/returns.2.hash | 1 + .../stable/py/other/ret/returns.2_0.hash | 1 + .../cases/stable/py/other/ret/returns.3.hash | 1 + .../stable/py/other/ret/returns.3_0.hash | 1 + .../cases/stable/py/other/ret/returns.4.hash | 1 + .../stable/py/other/ret/returns.4_0.hash | 1 + .../cases/stable/py/other/ret/returns.5.hash | 1 + .../stable/py/other/ret/returns.5_0.hash | 1 + .../cases/stable/py/other/ret/returns.6.hash | 1 + .../stable/py/other/ret/returns.6_0.hash | 1 + .../cases/stable/py/other/ret/returns.7.hash | 1 + .../stable/py/other/ret/returns.7_0.hash | 1 + .../cases/stable/py/other/ret/returns.8.hash | 1 + .../stable/py/other/ret/returns.8_0.hash | 1 + .../cases/stable/py/other/ret/returns.9.hash | 1 + .../stable/py/other/ret/returns.9_0.hash | 1 + .../stable/py/pitfalls/multi_contract.0.hash | 1 + .../cases/stable/py/pitfalls/pub_ctor.0.hash | 1 + .../stable/py/pitfalls/store_proxy.0.hash | 1 + .../stable/py/rollbacks/call_view.0.hash | 1 + .../stable/py/rollbacks/call_view.0_0.hash | 1 + .../stable/py/rollbacks/call_view.0_0_0.hash | 1 + .../py/rollbacks/calldata_rollback.0.hash | 1 + .../py/rollbacks/calldata_rollback.0_0.hash | 1 + .../py/rollbacks/calldata_rollback.0_0_0.hash | 1 + tests/cases/stable/py/rollbacks/nondet.0.hash | 1 + tests/cases/stable/py/rollbacks/simple.0.hash | 1 + .../py/sandbox/det/s/assign-json.0.hash | 1 + .../py/sandbox/det/s/assign-json.0_0.hash | 1 + .../cases/stable/py/sandbox/det/s/exit.0.hash | 1 + .../stable/py/sandbox/det/s/exit.0_0.hash | 1 + .../stable/py/sandbox/det/s/print.0.hash | 1 + .../stable/py/sandbox/det/s/print.0_0.hash | 1 + .../stable/py/sandbox/det/s/rollback.0.hash | 1 + .../stable/py/sandbox/det/s/rollback.0_0.hash | 1 + .../stable/py/sandbox/det/s/sandbox.0.hash | 1 + .../stable/py/sandbox/det/s/sandbox.0_0.hash | 1 + .../py/sandbox/det/sandbox_write.0.hash | 1 + .../py/sandbox/non-det/s/assign-json.0.hash | 1 + .../py/sandbox/non-det/s/assign-json.0_0.hash | 1 + .../stable/py/sandbox/non-det/s/exit.0.hash | 1 + .../stable/py/sandbox/non-det/s/exit.0_0.hash | 1 + .../stable/py/sandbox/non-det/s/print.0.hash | 1 + .../py/sandbox/non-det/s/print.0_0.hash | 1 + .../py/sandbox/non-det/s/rollback.0.hash | 1 + .../py/sandbox/non-det/s/rollback.0_0.hash | 1 + .../stable/py/schemas/complex_types.0.hash | 1 + .../stable/py/schemas/complex_types.0_0.hash | 1 + .../cases/stable/py/schemas/prim_types.0.hash | 1 + .../stable/py/schemas/prim_types.0_0.hash | 1 + .../cases/stable/py/schemas/ret-float.0.hash | 1 + .../stable/py/schemas/ret-float.0_0.hash | 1 + .../cases/stable/py/schemas/ret-tuple.0.hash | 1 + .../stable/py/schemas/ret-tuple.0_0.hash | 1 + tests/cases/stable/py/schemas/ret.0.hash | 1 + tests/cases/stable/py/schemas/ret.0_0.hash | 1 + tests/cases/stable/py/schemas/trivial.0.hash | 1 + .../cases/stable/py/schemas/trivial.0_0.hash | 1 + .../stable/runners/dup-dependency.0.hash | 1 + .../cases/stable/runners/env-template.0.hash | 1 + .../stable/runners/malformed_runner.0.hash | 1 + tests/cases/stable/runners/no_runner.0.hash | 1 + .../runners/nondet_custom_runner.0.hash | 1 + tests/cases/stable/runners/zip/no-zip.0.hash | 1 + tests/cases/stable/self-run/datetime.0.hash | 1 + tests/cases/stable/self-run/floats.0.hash | 1 + tests/cases/stable/self-run/formats.0.hash | 1 + tests/cases/stable/self-run/issue_163.0.hash | 1 + tests/cases/stable/self-run/module/np.0.hash | 1 + tests/cases/stable/self-run/module/pil.0.hash | 1 + tests/cases/stable/self-run/re.0.hash | 1 + .../cases/stable/self-run/typing_is_ok.0.hash | 1 + .../cases/stable/storage/alloc_generic.0.hash | 1 + .../stable/storage/alloc_generic_err.0.hash | 1 + tests/cases/stable/storage/base.0.hash | 1 + .../cases/stable/storage/bootstrapper.0.hash | 1 + .../stable/storage/bootstrapper.0_0.hash | 1 + .../stable/storage/bootstrapper.0_0_0.hash | 1 + .../stable/storage/bootstrapper.0_0_0_0.hash | 1 + .../storage/bootstrapper.0_0_0_0_0.hash | 1 + .../storage/bootstrapper.0_0_0_0_0_0.hash | 1 + tests/cases/stable/storage/floats.0.hash | 1 + tests/cases/stable/storage/gvm-89.0.hash | 1 + tests/cases/stable/storage/gvm-89.0_0.hash | 1 + .../storage/locking/default-frozen.0.hash | 1 + .../storage/locking/default-frozen.0_0.hash | 1 + .../storage/locking/default-frozen.0_0_0.hash | 1 + .../stable/storage/locking/modify_ctor.0.hash | 1 + .../storage/locking/modify_ctor.0_0.hash | 1 + .../storage/locking/modify_later.0.hash | 1 + .../storage/locking/modify_later.0_0.hash | 1 + .../storage/locking/modify_later.0_0_0.hash | 1 + tests/cases/stable/storage/np.0.hash | 1 + tests/cases/stable/storage/persists.0.hash | 1 + tests/cases/stable/storage/persists.0_0.hash | 1 + tests/cases/stable/storage/read_nondet.0.hash | 1 + .../stable/storage/storage_tree_map.0.hash | 1 + tests/cases/stable/storage/to_str.0.hash | 1 + .../stable/storage/tree_map_nested.0.hash | 1 + ...eq_prompt_non_comparative_validator.0.hash | 1 + ...rompt_non_comparative_validator_bad.0.hash | 1 + .../unstable/nondet/validator/agree.0.hash | 1 + .../unstable/nondet/validator/agree.0_0.hash | 1 + .../unstable/nondet/validator/disagree.0.hash | 1 + .../nondet/validator/disagree.0_0.hash | 1 + .../nondet/web/get_webpage_html.0.hash | 1 + .../nondet/web/get_webpage_screenshot.0.hash | 1 + .../nondet/web/get_webpage_text.0.hash | 1 + .../cases/unstable/nondet/web/sandbox.0.hash | 1 + 242 files changed, 275 insertions(+), 49 deletions(-) create mode 100644 tests/cases/_hello_world_.0.hash create mode 100644 tests/cases/_hello_world_class.0.hash create mode 100644 tests/cases/_hello_world_class.0_0.hash create mode 100644 tests/cases/_hello_world_class_nondet.0.hash create mode 100644 tests/cases/semi-stable/llm/percent_in_prompt.0.hash create mode 100644 tests/cases/semi-stable/llm/woc.0.hash create mode 100644 tests/cases/semi-stable/llm/woc.0_0.hash create mode 100644 tests/cases/semi-stable/llm/woc.0_0_0_0.hash create mode 100644 tests/cases/semi-stable/web/file_schema_web_bash.0.hash create mode 100644 tests/cases/semi-stable/web/file_schema_web_proc.0.hash create mode 100644 tests/cases/semi-stable/web/request_signed.0.hash create mode 100644 tests/cases/stable/agentic/wasi/environ_args/environ_args.0.hash create mode 100644 tests/cases/stable/agentic/wasi/hash_random/hash_random.0.hash create mode 100644 tests/cases/stable/agentic/wasi/set_order/set_order.0.hash create mode 100644 tests/cases/stable/agentic/wasi/wasi_clock/wasi_clock.0.hash create mode 100644 tests/cases/stable/agentic/wasi/wasi_random/wasi_random.0.hash create mode 100644 tests/cases/stable/exploits/call_wasi_extra.0.hash create mode 100644 tests/cases/stable/exploits/close_std.0.hash create mode 100644 tests/cases/stable/exploits/deep_calldata.0.hash create mode 100644 tests/cases/stable/exploits/disagree_in_sandbox.0.hash create mode 100644 tests/cases/stable/exploits/flt.0.hash create mode 100644 tests/cases/stable/exploits/fork_bomb.0.hash create mode 100644 tests/cases/stable/exploits/method_init.0.hash create mode 100644 tests/cases/stable/exploits/method_init.0_0.hash create mode 100644 tests/cases/stable/exploits/method_private.0.hash create mode 100644 tests/cases/stable/exploits/method_private.0_0.hash create mode 100644 tests/cases/stable/exploits/oom.0.hash create mode 100644 tests/cases/stable/exploits/rec.0.hash create mode 100644 tests/cases/stable/exploits/rec_1023.0.hash create mode 100644 tests/cases/stable/exploits/rec_1024.0.hash create mode 100644 tests/cases/stable/exploits/storage_page_limit.0.hash create mode 100644 tests/cases/stable/exploits/storage_page_limit.0_0.hash create mode 100644 tests/cases/stable/exploits/storage_page_limit.0_1.hash create mode 100644 tests/cases/stable/exploits/storage_rw_long.0.hash create mode 100644 tests/cases/stable/exploits/storage_rw_long.0_0.hash create mode 100644 tests/cases/stable/exploits/subtract_on_start_underflow.0.hash create mode 100644 tests/cases/stable/exploits/unreachable.0.hash create mode 100644 tests/cases/stable/nondet/leader_errors/empty_leader_result.0.hash create mode 100644 tests/cases/stable/nondet/leader_errors/empty_leader_result.0_0.hash create mode 100644 tests/cases/stable/nondet/leader_errors/leader_no_nondet.0.hash create mode 100644 tests/cases/stable/nondet/leader_errors/leader_no_nondet.0_0.hash create mode 100644 tests/cases/stable/nondet/leader_errors/simple_leader.0.hash create mode 100644 tests/cases/stable/nondet/leader_errors/simple_leader.0_0.hash create mode 100644 tests/cases/stable/nondet/leader_errors/simple_valid_err_err.0.hash create mode 100644 tests/cases/stable/nondet/leader_errors/simple_valid_err_err.0_0.hash create mode 100644 tests/cases/stable/nondet/leader_errors/simple_valid_err_exit.0.hash create mode 100644 tests/cases/stable/nondet/leader_errors/simple_valid_err_exit.0_0.hash create mode 100644 tests/cases/stable/nondet/leader_errors/simple_valid_err_exit_wrong_err.0.hash create mode 100644 tests/cases/stable/nondet/leader_errors/simple_valid_err_exit_wrong_err.0_0.hash create mode 100644 tests/cases/stable/nondet/leader_errors/simple_valid_err_nerr.0.hash create mode 100644 tests/cases/stable/nondet/leader_errors/simple_valid_err_nerr.0_0.hash create mode 100644 tests/cases/stable/nondet/metod_det_get_webpage.0.hash create mode 100644 tests/cases/stable/nondet/metod_det_get_webpage.0_0.hash create mode 100644 tests/cases/stable/nondet/trivial.0.hash create mode 100644 tests/cases/stable/nondet/trivial.0_0.hash create mode 100644 tests/cases/stable/nondet/validator/rollback_agree.0.hash create mode 100644 tests/cases/stable/nondet/validator/rollback_agree.0_0.hash create mode 100644 tests/cases/stable/nondet/validator/rollback_disagree.0.hash create mode 100644 tests/cases/stable/nondet/validator/rollback_disagree.0_0.hash create mode 100644 tests/cases/stable/nondet/validator/rollback_imm.0.hash create mode 100644 tests/cases/stable/nondet/validator/rollback_imm.0_0.hash create mode 100644 tests/cases/stable/nondet/validator/rollback_imm.0_1.hash create mode 100644 tests/cases/stable/nondet/validator/rollback_imm.0_2.hash create mode 100644 tests/cases/stable/nondet/validator/sync.0.hash create mode 100644 tests/cases/stable/nondet/validator/sync.0_0.hash create mode 100644 tests/cases/stable/nondet/validator/sync_err.0.hash create mode 100644 tests/cases/stable/nondet/validator/sync_err.0_0.hash create mode 100644 tests/cases/stable/py/balances/balance.0.hash create mode 100644 tests/cases/stable/py/balances/balance.0_0.hash create mode 100644 tests/cases/stable/py/balances/balance_eth.0.hash create mode 100644 tests/cases/stable/py/balances/balance_eth.0_0.hash create mode 100644 tests/cases/stable/py/balances/sandbox_overspend.0.hash create mode 100644 tests/cases/stable/py/balances/sandbox_overspend_2.0.hash create mode 100644 tests/cases/stable/py/balances/undefined_all.0.hash create mode 100644 tests/cases/stable/py/balances/undefined_all.0_0.hash create mode 100644 tests/cases/stable/py/balances/undefined_all.0_0_0.hash create mode 100644 tests/cases/stable/py/balances/undefined_method.0.hash create mode 100644 tests/cases/stable/py/balances/undefined_method.0_0.hash create mode 100644 tests/cases/stable/py/balances/undefined_method.0_0_0.hash create mode 100644 tests/cases/stable/py/balances/undefined_method_payable.0.hash create mode 100644 tests/cases/stable/py/balances/undefined_method_payable.0_0.hash create mode 100644 tests/cases/stable/py/balances/undefined_method_payable.0_0_0.hash create mode 100644 tests/cases/stable/py/balances/undefined_receive.0.hash create mode 100644 tests/cases/stable/py/balances/undefined_receive.0_0.hash create mode 100644 tests/cases/stable/py/balances/undefined_receive.0_0_0.hash create mode 100644 tests/cases/stable/py/embeddings/simple.0.hash create mode 100644 tests/cases/stable/py/embeddings/simple.0_0.hash create mode 100644 tests/cases/stable/py/embeddings/simple_det.0.hash create mode 100644 tests/cases/stable/py/embeddings/simple_det.0_0.hash create mode 100644 tests/cases/stable/py/embeddings/simple_tokenizer.0.hash create mode 100644 tests/cases/stable/py/embeddings/simple_tokenizer.0_0.hash create mode 100644 tests/cases/stable/py/embeddings/vecdb.0.hash create mode 100644 tests/cases/stable/py/events/post_event.0.hash create mode 100644 tests/cases/stable/py/intercontract/call_self_view.0.hash create mode 100644 tests/cases/stable/py/intercontract/call_view.0.hash create mode 100644 tests/cases/stable/py/intercontract/call_view.0_0.hash create mode 100644 tests/cases/stable/py/intercontract/call_view.0_0_0.hash create mode 100644 tests/cases/stable/py/intercontract/call_view_committed.0.hash create mode 100644 tests/cases/stable/py/intercontract/call_view_committed.0_0.hash create mode 100644 tests/cases/stable/py/intercontract/call_view_emit.0.hash create mode 100644 tests/cases/stable/py/intercontract/call_view_emit.0_0.hash create mode 100644 tests/cases/stable/py/intercontract/call_view_emit.0_0_0.hash create mode 100644 tests/cases/stable/py/intercontract/call_view_iface.0.hash create mode 100644 tests/cases/stable/py/intercontract/call_view_iface.0_0.hash create mode 100644 tests/cases/stable/py/intercontract/call_view_iface.0_0_0.hash create mode 100644 tests/cases/stable/py/intercontract/deploy.0.hash create mode 100644 tests/cases/stable/py/intercontract/deploy_salt.0.hash create mode 100644 tests/cases/stable/py/intercontract/eth_call_view.0.hash create mode 100644 tests/cases/stable/py/intercontract/send_message.0.hash create mode 100644 tests/cases/stable/py/intercontract/send_message_eth.0.hash create mode 100644 tests/cases/stable/py/intercontract/send_message_on.0.hash create mode 100644 tests/cases/stable/py/intercontract/send_message_on.0_0.hash create mode 100644 tests/cases/stable/py/intercontract/send_message_on.0_0_0.hash create mode 100644 tests/cases/stable/py/other/meth/method_init.0.hash create mode 100644 tests/cases/stable/py/other/meth/method_init_wrong_name.0.hash create mode 100644 tests/cases/stable/py/other/meth/method_public.0.hash create mode 100644 tests/cases/stable/py/other/meth/method_public.0_0.hash create mode 100644 tests/cases/stable/py/other/meth/method_retn.0.hash create mode 100644 tests/cases/stable/py/other/meth/method_retn.0_0.hash create mode 100644 tests/cases/stable/py/other/meth/method_retn_view.0.hash create mode 100644 tests/cases/stable/py/other/meth/method_retn_view.0_0.hash create mode 100644 tests/cases/stable/py/other/meth/method_rollback.0.hash create mode 100644 tests/cases/stable/py/other/meth/method_rollback.0_0.hash create mode 100644 tests/cases/stable/py/other/ret/returns.0.hash create mode 100644 tests/cases/stable/py/other/ret/returns.0_0.hash create mode 100644 tests/cases/stable/py/other/ret/returns.1.hash create mode 100644 tests/cases/stable/py/other/ret/returns.1_0.hash create mode 100644 tests/cases/stable/py/other/ret/returns.2.hash create mode 100644 tests/cases/stable/py/other/ret/returns.2_0.hash create mode 100644 tests/cases/stable/py/other/ret/returns.3.hash create mode 100644 tests/cases/stable/py/other/ret/returns.3_0.hash create mode 100644 tests/cases/stable/py/other/ret/returns.4.hash create mode 100644 tests/cases/stable/py/other/ret/returns.4_0.hash create mode 100644 tests/cases/stable/py/other/ret/returns.5.hash create mode 100644 tests/cases/stable/py/other/ret/returns.5_0.hash create mode 100644 tests/cases/stable/py/other/ret/returns.6.hash create mode 100644 tests/cases/stable/py/other/ret/returns.6_0.hash create mode 100644 tests/cases/stable/py/other/ret/returns.7.hash create mode 100644 tests/cases/stable/py/other/ret/returns.7_0.hash create mode 100644 tests/cases/stable/py/other/ret/returns.8.hash create mode 100644 tests/cases/stable/py/other/ret/returns.8_0.hash create mode 100644 tests/cases/stable/py/other/ret/returns.9.hash create mode 100644 tests/cases/stable/py/other/ret/returns.9_0.hash create mode 100644 tests/cases/stable/py/pitfalls/multi_contract.0.hash create mode 100644 tests/cases/stable/py/pitfalls/pub_ctor.0.hash create mode 100644 tests/cases/stable/py/pitfalls/store_proxy.0.hash create mode 100644 tests/cases/stable/py/rollbacks/call_view.0.hash create mode 100644 tests/cases/stable/py/rollbacks/call_view.0_0.hash create mode 100644 tests/cases/stable/py/rollbacks/call_view.0_0_0.hash create mode 100644 tests/cases/stable/py/rollbacks/calldata_rollback.0.hash create mode 100644 tests/cases/stable/py/rollbacks/calldata_rollback.0_0.hash create mode 100644 tests/cases/stable/py/rollbacks/calldata_rollback.0_0_0.hash create mode 100644 tests/cases/stable/py/rollbacks/nondet.0.hash create mode 100644 tests/cases/stable/py/rollbacks/simple.0.hash create mode 100644 tests/cases/stable/py/sandbox/det/s/assign-json.0.hash create mode 100644 tests/cases/stable/py/sandbox/det/s/assign-json.0_0.hash create mode 100644 tests/cases/stable/py/sandbox/det/s/exit.0.hash create mode 100644 tests/cases/stable/py/sandbox/det/s/exit.0_0.hash create mode 100644 tests/cases/stable/py/sandbox/det/s/print.0.hash create mode 100644 tests/cases/stable/py/sandbox/det/s/print.0_0.hash create mode 100644 tests/cases/stable/py/sandbox/det/s/rollback.0.hash create mode 100644 tests/cases/stable/py/sandbox/det/s/rollback.0_0.hash create mode 100644 tests/cases/stable/py/sandbox/det/s/sandbox.0.hash create mode 100644 tests/cases/stable/py/sandbox/det/s/sandbox.0_0.hash create mode 100644 tests/cases/stable/py/sandbox/det/sandbox_write.0.hash create mode 100644 tests/cases/stable/py/sandbox/non-det/s/assign-json.0.hash create mode 100644 tests/cases/stable/py/sandbox/non-det/s/assign-json.0_0.hash create mode 100644 tests/cases/stable/py/sandbox/non-det/s/exit.0.hash create mode 100644 tests/cases/stable/py/sandbox/non-det/s/exit.0_0.hash create mode 100644 tests/cases/stable/py/sandbox/non-det/s/print.0.hash create mode 100644 tests/cases/stable/py/sandbox/non-det/s/print.0_0.hash create mode 100644 tests/cases/stable/py/sandbox/non-det/s/rollback.0.hash create mode 100644 tests/cases/stable/py/sandbox/non-det/s/rollback.0_0.hash create mode 100644 tests/cases/stable/py/schemas/complex_types.0.hash create mode 100644 tests/cases/stable/py/schemas/complex_types.0_0.hash create mode 100644 tests/cases/stable/py/schemas/prim_types.0.hash create mode 100644 tests/cases/stable/py/schemas/prim_types.0_0.hash create mode 100644 tests/cases/stable/py/schemas/ret-float.0.hash create mode 100644 tests/cases/stable/py/schemas/ret-float.0_0.hash create mode 100644 tests/cases/stable/py/schemas/ret-tuple.0.hash create mode 100644 tests/cases/stable/py/schemas/ret-tuple.0_0.hash create mode 100644 tests/cases/stable/py/schemas/ret.0.hash create mode 100644 tests/cases/stable/py/schemas/ret.0_0.hash create mode 100644 tests/cases/stable/py/schemas/trivial.0.hash create mode 100644 tests/cases/stable/py/schemas/trivial.0_0.hash create mode 100644 tests/cases/stable/runners/dup-dependency.0.hash create mode 100644 tests/cases/stable/runners/env-template.0.hash create mode 100644 tests/cases/stable/runners/malformed_runner.0.hash create mode 100644 tests/cases/stable/runners/no_runner.0.hash create mode 100644 tests/cases/stable/runners/nondet_custom_runner.0.hash create mode 100644 tests/cases/stable/runners/zip/no-zip.0.hash create mode 100644 tests/cases/stable/self-run/datetime.0.hash create mode 100644 tests/cases/stable/self-run/floats.0.hash create mode 100644 tests/cases/stable/self-run/formats.0.hash create mode 100644 tests/cases/stable/self-run/issue_163.0.hash create mode 100644 tests/cases/stable/self-run/module/np.0.hash create mode 100644 tests/cases/stable/self-run/module/pil.0.hash create mode 100644 tests/cases/stable/self-run/re.0.hash create mode 100644 tests/cases/stable/self-run/typing_is_ok.0.hash create mode 100644 tests/cases/stable/storage/alloc_generic.0.hash create mode 100644 tests/cases/stable/storage/alloc_generic_err.0.hash create mode 100644 tests/cases/stable/storage/base.0.hash create mode 100644 tests/cases/stable/storage/bootstrapper.0.hash create mode 100644 tests/cases/stable/storage/bootstrapper.0_0.hash create mode 100644 tests/cases/stable/storage/bootstrapper.0_0_0.hash create mode 100644 tests/cases/stable/storage/bootstrapper.0_0_0_0.hash create mode 100644 tests/cases/stable/storage/bootstrapper.0_0_0_0_0.hash create mode 100644 tests/cases/stable/storage/bootstrapper.0_0_0_0_0_0.hash create mode 100644 tests/cases/stable/storage/floats.0.hash create mode 100644 tests/cases/stable/storage/gvm-89.0.hash create mode 100644 tests/cases/stable/storage/gvm-89.0_0.hash create mode 100644 tests/cases/stable/storage/locking/default-frozen.0.hash create mode 100644 tests/cases/stable/storage/locking/default-frozen.0_0.hash create mode 100644 tests/cases/stable/storage/locking/default-frozen.0_0_0.hash create mode 100644 tests/cases/stable/storage/locking/modify_ctor.0.hash create mode 100644 tests/cases/stable/storage/locking/modify_ctor.0_0.hash create mode 100644 tests/cases/stable/storage/locking/modify_later.0.hash create mode 100644 tests/cases/stable/storage/locking/modify_later.0_0.hash create mode 100644 tests/cases/stable/storage/locking/modify_later.0_0_0.hash create mode 100644 tests/cases/stable/storage/np.0.hash create mode 100644 tests/cases/stable/storage/persists.0.hash create mode 100644 tests/cases/stable/storage/persists.0_0.hash create mode 100644 tests/cases/stable/storage/read_nondet.0.hash create mode 100644 tests/cases/stable/storage/storage_tree_map.0.hash create mode 100644 tests/cases/stable/storage/to_str.0.hash create mode 100644 tests/cases/stable/storage/tree_map_nested.0.hash create mode 100644 tests/cases/unstable/nondet/eq/ncomp/eq_prompt_non_comparative_validator.0.hash create mode 100644 tests/cases/unstable/nondet/eq/ncomp/eq_prompt_non_comparative_validator_bad.0.hash create mode 100644 tests/cases/unstable/nondet/validator/agree.0.hash create mode 100644 tests/cases/unstable/nondet/validator/agree.0_0.hash create mode 100644 tests/cases/unstable/nondet/validator/disagree.0.hash create mode 100644 tests/cases/unstable/nondet/validator/disagree.0_0.hash create mode 100644 tests/cases/unstable/nondet/web/get_webpage_html.0.hash create mode 100644 tests/cases/unstable/nondet/web/get_webpage_screenshot.0.hash create mode 100644 tests/cases/unstable/nondet/web/get_webpage_text.0.hash create mode 100644 tests/cases/unstable/nondet/web/sandbox.0.hash diff --git a/executor/crates/common/build.rs b/executor/crates/common/build.rs index b55b44a33..609fd1368 100644 --- a/executor/crates/common/build.rs +++ b/executor/crates/common/build.rs @@ -16,7 +16,7 @@ fn main() -> std::io::Result<()> { let profile = std::env::var("PROFILE").unwrap(); println!("cargo::rustc-env=PROFILE={profile}"); - let tag = tag.replace("-", "_"); + // tag can have `-`, parse from the right let arch = arch.replace("-", "_"); let os = os.replace("-", "_"); let profile = profile.replace("-", "_"); diff --git a/executor/fuzz/genvm-storage.rs b/executor/fuzz/genvm-storage.rs index e26de76aa..cde883e4f 100644 --- a/executor/fuzz/genvm-storage.rs +++ b/executor/fuzz/genvm-storage.rs @@ -155,27 +155,27 @@ async fn run_storage_fuzz(input: FuzzInput) -> anyhow::Result<()> { genvm::config::FeesConfig { expr_prelude: String::new(), storage: genvm::config::FeesBucketConfig { - bucket_no: 0, + bucket_no: vec![0], subtract_on_start_expr: "0".into(), delta_expr: r"\attrs = 0".into(), }, message_receipt: genvm::config::FeesBucketConfig { - bucket_no: 0, + bucket_no: vec![0], subtract_on_start_expr: "0".into(), delta_expr: r"\attrs = 0".into(), }, nondet_output: genvm::config::FeesBucketConfig { - bucket_no: 0, + bucket_no: vec![0], subtract_on_start_expr: "0".into(), delta_expr: r"\attrs = 0".into(), }, message_fee: genvm::config::FeesBucketConfig { - bucket_no: 0, + bucket_no: vec![0], subtract_on_start_expr: "0".into(), delta_expr: r"\attrs = 0".into(), }, event: genvm::config::FeesBucketConfig { - bucket_no: 0, + bucket_no: vec![0], subtract_on_start_expr: "0".into(), delta_expr: r"\attrs = 0".into(), }, diff --git a/executor/tests/runner_id.rs b/executor/tests/runner_id.rs index bec277f80..d3367f19e 100644 --- a/executor/tests/runner_id.rs +++ b/executor/tests/runner_id.rs @@ -1,6 +1,5 @@ use genvm::calldata::Address; -use genvm::public_abi::StorageType; -use genvm::runners::{self, Id, IdUnresolved}; +use genvm::runners::{self, ChainState, Id, IdUnresolved}; use genvm::SlotID; fn test_addr() -> String { @@ -20,7 +19,7 @@ fn chain_canonical_uses_checksum_address() { let id = Id::Chain { address, - on: StorageType::LatestNonFinal, + on: ChainState::Accepted, slot: SlotID::ZERO, }; @@ -50,14 +49,14 @@ fn parse_runner_id_forms() { match runners::parse_runner_id(&format!("chain:{}:f:{}", test_addr(), test_slot())) { Some(IdUnresolved::Chain { on, slot, .. }) => { - assert_eq!(on, Some(StorageType::LatestFinal)); + assert_eq!(on, Some(ChainState::Finalized)); assert!(slot.is_some()); } other => panic!("expected Chain, got {other:?}"), } match runners::parse_runner_id(&format!("chain:{}:a:{}", test_addr(), test_slot())) { Some(IdUnresolved::Chain { on, slot, .. }) => { - assert_eq!(on, Some(StorageType::LatestNonFinal)); + assert_eq!(on, Some(ChainState::Accepted)); assert!(slot.is_some()); } other => panic!("expected Chain, got {other:?}"), @@ -94,7 +93,7 @@ fn parse_runner_id_rejects_malformed() { fn chain_without_slot_id() { match runners::parse_runner_id(&format!("chain:{}:a", test_addr())) { Some(IdUnresolved::Chain { on, slot, .. }) => { - assert_eq!(on, Some(StorageType::LatestNonFinal)); + assert_eq!(on, Some(ChainState::Accepted)); assert!(slot.is_none(), "slot must be None when omitted"); } other => panic!("expected Chain, got {other:?}"), @@ -105,7 +104,7 @@ fn chain_without_slot_id() { fn chain_without_on_or_slot() { match runners::parse_runner_id(&format!("chain:{}", test_addr())) { Some(IdUnresolved::Chain { on, slot, .. }) => { - assert_eq!(on, Some(StorageType::LatestNonFinal)); + assert_eq!(on, Some(ChainState::Accepted)); assert!(slot.is_none(), "slot must be None when omitted"); } other => panic!("expected Chain, got {other:?}"), @@ -116,26 +115,9 @@ fn chain_without_on_or_slot() { fn chain_with_explicit_slot() { match runners::parse_runner_id(&format!("chain:{}:f:{}", test_addr(), test_slot())) { Some(IdUnresolved::Chain { on, slot, .. }) => { - assert_eq!(on, Some(StorageType::LatestFinal)); + assert_eq!(on, Some(ChainState::Finalized)); assert!(slot.is_some(), "slot must be Some when given"); } other => panic!("expected Chain, got {other:?}"), } } - -#[test] -fn chain_resolve_fills_contract_fields() { - let parsed = runners::parse_runner_id(&format!("chain:{}", test_addr())).unwrap(); - let contract_addr = Address::from([0xAA; 20]); - let state = StorageType::LatestFinal; - let code_slot = SlotID::from_bytes([0xBB; 32]); - let resolved = parsed.resolve(contract_addr, state, code_slot); - match resolved { - IdUnresolved::Chain { on, slot, address } => { - assert_ne!(address, contract_addr, "chain: keeps its own address"); - assert_eq!(on, Some(StorageType::LatestNonFinal)); - assert!(slot.is_none(), "chain: slot is not filled by resolve"); - } - _ => panic!("expected Chain"), - } -} diff --git a/modules/install/lib/python/post-install/__main__.py b/modules/install/lib/python/post-install/__main__.py index eb15030bd..d8333fae6 100644 --- a/modules/install/lib/python/post-install/__main__.py +++ b/modules/install/lib/python/post-install/__main__.py @@ -170,24 +170,26 @@ def str_to_bool_or_none(value): lief.logging.set_level(lief.logging.LEVEL.ERROR) -HASH_VALID_CHARS = '0123456789abcdfghijklmnpqrsvwxyz' +# gvm32 (Crockford's Base32, big-endian, no padding) — the encoding the executor +# uses for runner hashes / on-disk paths. MUST match support/runner-script.py, +# executor/crates/sdk-rs/src/gvm32.rs and runners/genlayer-py-std/.../gvm32.py. +# NOT Nix base32 (which uses a different alphabet AND little-endian bit order). +HASH_VALID_CHARS = '0123456789abcdefghjkmnpqrstvwxyz' def digest_to_hash_id(got_hash: bytes) -> str: - chars = '0123456789abcdfghijklmnpqrsvwxyz' - - bytes_count = len(got_hash) - base32_len = (bytes_count * 8 - 1) // 5 + 1 - - my_hash_arr = [] - for n in range(base32_len - 1, -1, -1): - b = n * 5 - i = b // 8 - j = b % 8 - c = (got_hash[i] >> j) | (0 if i >= bytes_count - 1 else got_hash[i + 1] << (8 - j)) - my_hash_arr.append(chars[c & 0x1F]) - - return ''.join(my_hash_arr) + out = [] + value = 0 + bits = 0 + for byte in got_hash: + value = (value << 8) | byte + bits += 8 + while bits >= 5: + bits -= 5 + out.append(HASH_VALID_CHARS[(value >> bits) & 0x1F]) + if bits > 0: + out.append(HASH_VALID_CHARS[(value << (5 - bits)) & 0x1F]) + return ''.join(out) def runner_check_bytes(data: bytes, hash: str) -> bool: diff --git a/runners/support/views/docs.nix b/runners/support/views/docs.nix index e269033f8..5b99bbd10 100644 --- a/runners/support/views/docs.nix +++ b/runners/support/views/docs.nix @@ -11,7 +11,9 @@ let old_l_elem = if builtins.hasAttr rev_id l then l.${rev_id} else {}; old_l_id = if builtins.hasAttr r.id old_l_elem then old_l_elem.${r.id} else {}; - r_hash = if r.hash == "test" then "vTEST" else builtins.convertHash { hash = r.hash; toHashFormat = "nix32"; }; + # gvm32 (Crockford Base32) — the encoding the executor uses for runner + # paths. Extract it from `uid` (`id:gvm32hash`); NOT Nix base32. + r_hash = if r.hash == "test" then "vTEST" else builtins.head (builtins.match "[^:]+:(.*)" r.uid); new_l_id = old_l_id // { ${r_hash} = true; }; new_l_elem = old_l_elem // { ${r.id} = new_l_id; }; diff --git a/support/ci/pipelines/test-rust.sh b/support/ci/pipelines/test-rust.sh index c81d27865..37d8f7877 100755 --- a/support/ci/pipelines/test-rust.sh +++ b/support/ci/pipelines/test-rust.sh @@ -8,12 +8,16 @@ export ORIGINAL_LD_LIBRARY_PATH="$LD_LIBRARY_PATH" mkdir -p build/out/executor/vTEST/data +# gvm32 (Crockford Base32) is the encoding the executor uses for runner paths; +# it is carried in `x.uid` as `id:gvm32hash`. Do NOT use `toHashFormat = "nix32"` +# here: Nix base32 has a different alphabet, so the registry names would never +# match the on-disk tars / GCS objects (e.g. nix32 `04l343…` vs gvm32 `5tnhg…`). nix eval --verbose --impure --read-only --show-trace --json --expr \ - 'let drv = import ./runners { host-system = builtins.currentSystem; } ; in builtins.listToAttrs (builtins.map (x: { name = x.id; value = builtins.convertHash { hash = x.hash; toHashFormat = "nix32"; }; }) drv)' \ + 'let drv = import ./runners { host-system = builtins.currentSystem; } ; in builtins.listToAttrs (builtins.map (x: { name = x.id; value = builtins.head (builtins.match "[^:]+:(.*)" x.uid); }) drv)' \ > build/out/executor/vTEST/data/latest.json nix eval --verbose --impure --read-only --show-trace --json --expr \ - 'let drv = import ./runners { host-system = builtins.currentSystem; } ; in builtins.listToAttrs (builtins.map (x: { name = x.id; value = [ (builtins.convertHash { hash = x.hash; toHashFormat = "nix32"; }) ]; }) drv)' \ + 'let drv = import ./runners { host-system = builtins.currentSystem; } ; in builtins.listToAttrs (builtins.map (x: { name = x.id; value = [ (builtins.head (builtins.match "[^:]+:(.*)" x.uid)) ]; }) drv)' \ > build/out/executor/vTEST/data/all.json # we can't run it within nix because it uses `nix add` which sigsegvs diff --git a/tests/cases/_hello_world_.0.hash b/tests/cases/_hello_world_.0.hash new file mode 100644 index 000000000..4bca7eb33 --- /dev/null +++ b/tests/cases/_hello_world_.0.hash @@ -0,0 +1 @@ +LQEAABUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgwQ2AAAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCnByaW50KDEpCmV4aXQoMCkKAAAAAAAABQ== diff --git a/tests/cases/_hello_world_class.0.hash b/tests/cases/_hello_world_class.0.hash new file mode 100644 index 000000000..55b568994 --- /dev/null +++ b/tests/cases/_hello_world_class.0.hash @@ -0,0 +1 @@ +LQEAACUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxQ7AQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6Cgljb3VudGVyOiB1OAoKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwcmludChmJ2hlbGxvIHdvcmxkIHtzZWxmLmNvdW50ZXJ9JykKCQlzZWxmLmNvdW50ZXIgKz0gMQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBmb28oc2VsZik6CgkJcHJpbnQoZidoZWxsbyB3b3JsZCB7c2VsZi5jb3VudGVyfScpCgkJc2VsZi5jb3VudGVyICs9IDEKABWjAuGuI0Enkt9rapj7fJg5cB+4sCtvx+0CKBD3g0ZJRoXnAAAAAIMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/_hello_world_class.0_0.hash b/tests/cases/_hello_world_class.0_0.hash new file mode 100644 index 000000000..1383f83c8 --- /dev/null +++ b/tests/cases/_hello_world_class.0_0.hash @@ -0,0 +1 @@ +LQEAAA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/_hello_world_class_nondet.0.hash b/tests/cases/_hello_world_class_nondet.0.hash new file mode 100644 index 000000000..26b60dfab --- /dev/null +++ b/tests/cases/_hello_world_class_nondet.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxZPAQAAIyB2MC4xLjEwCiMgewojICAgIlNlcSI6IFsKIyAgICAgeyAiQWRkRW52IjogeyJuYW1lIjogIkdFTkxBWUVSX0VOQUJMRV9QUk9GSUxFUiIsICJ2YWwiOiAiZmFsc2UifSB9LAojICAgICB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KIyAgIF0KIyB9CmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJZGVmIF9faW5pdF9fKHNlbGYpOgoJCWdsLnZtLnJ1bl9ub25kZXQobGFtYmRhOiBOb25lLCBsYW1iZGEgeDogVHJ1ZSkKCQlwcmludCgnaGVsbG8gd29ybGQnKQoAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/semi-stable/llm/percent_in_prompt.0.hash b/tests/cases/semi-stable/llm/percent_in_prompt.0.hash new file mode 100644 index 000000000..3c52cd5da --- /dev/null +++ b/tests/cases/semi-stable/llm/percent_in_prompt.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxIFAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJZGVmIHJ1bigpOgoJCQlyZXR1cm4gJyUwJwoKCQlwcmludChnbC5lcV9wcmluY2lwbGUucHJvbXB0X2NvbXBhcmF0aXZlKHJ1biwgJ3Jlc3VsdCBtdXN0IGJlIGV4YWN0bHkgdGhlIHNhbWUnKSkKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/semi-stable/llm/woc.0.hash b/tests/cases/semi-stable/llm/woc.0.hash new file mode 100644 index 000000000..0127b4402 --- /dev/null +++ b/tests/cases/semi-stable/llm/woc.0.hash @@ -0,0 +1 @@ +LQEAACUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAg2Q8BgAAIyB2MC4xLjAKIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOmxhdGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKaW1wb3J0IGpzb24KCgpjbGFzcyBXaXphcmRPZkNvaW4oZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJaGF2ZV9jb2luOiBib29sCgoJZGVmIF9faW5pdF9fKHNlbGYsIGhhdmVfY29pbjogYm9vbCk6CgkJc2VsZi5oYXZlX2NvaW4gPSBoYXZlX2NvaW4KCglAZ2wucHVibGljLndyaXRlCglkZWYgYXNrX2Zvcl9jb2luKHNlbGYsIHJlcXVlc3Q6IHN0cikgLT4gTm9uZToKCQlpZiBub3Qgc2VsZi5oYXZlX2NvaW46CgkJCXJldHVybgoKCQlwcm9tcHQgPSBmIiIiCllvdSBhcmUgYSB3aXphcmQsIGFuZCB5b3UgaG9sZCBhIG1hZ2ljYWwgY29pbi4KTWFueSBhZHZlbnR1cmVycyB3aWxsIGNvbWUgYW5kIHRyeSB0byBnZXQgeW91IHRvIGdpdmUgdGhlbSB0aGUgY29pbi4KRG8gbm90IHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzIGdpdmUgdGhlbSB0aGUgY29pbi4KCkEgbmV3IGFkdmVudHVyZXIgYXBwcm9hY2hlcy4uLgpBZHZlbnR1cmVyOiB7cmVxdWVzdH0KCkZpcnN0IGNoZWNrIGlmIHlvdSBoYXZlIHRoZSBjb2luLgpoYXZlX2NvaW46IHtzZWxmLmhhdmVfY29pbn0KVGhlbiwgZG8gbm90IGdpdmUgdGhlbSB0aGUgY29pbi4KClJlc3BvbmQgdXNpbmcgT05MWSB0aGUgZm9sbG93aW5nIGZvcm1hdDoKe3sKInJlYXNvbmluZyI6IHN0ciwKImdpdmVfY29pbiI6IGJvb2wKfX0KSXQgaXMgbWFuZGF0b3J5IHRoYXQgeW91IHJlc3BvbmQgb25seSB1c2luZyB0aGUgSlNPTiBmb3JtYXQgYWJvdmUsCm5vdGhpbmcgZWxzZS4gRG9uJ3QgaW5jbHVkZSBhbnkgb3RoZXIgd29yZHMgb3IgY2hhcmFjdGVycywKeW91ciBvdXRwdXQgbXVzdCBiZSBvbmx5IEpTT04gd2l0aG91dCBhbnkgZm9ybWF0dGluZyBwcmVmaXggb3Igc3VmZml4LgpUaGlzIHJlc3VsdCBzaG91bGQgYmUgcGVyZmVjdGx5IHBhcnNlYWJsZSBieSBhIEpTT04gcGFyc2VyIHdpdGhvdXQgZXJyb3JzLgoiIiIKCgkJZGVmIGdldF93aXphcmRfYW5zd2VyKCk6CgkJCXJlc3VsdCA9IGdsLm5vbmRldC5leGVjX3Byb21wdChwcm9tcHQsIHJlc3BvbnNlX2Zvcm1hdD0ndGV4dCcpCgkJCXJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKCdgYGBqc29uJywgJycpLnJlcGxhY2UoJ2BgYCcsICcnKQoJCQlyZXR1cm4gcmVzdWx0CgoJCXJlc3VsdCA9IGdsLmVxX3ByaW5jaXBsZS5wcm9tcHRfY29tcGFyYXRpdmUoCgkJCWdldF93aXphcmRfYW5zd2VyLCAnVGhlIHZhbHVlIG9mIGdpdmVfY29pbiBoYXMgdG8gbWF0Y2gnCgkJKQoJCXBhcnNlZF9yZXN1bHQgPSBqc29uLmxvYWRzKHJlc3VsdCkKCQlhc3NlcnQgaXNpbnN0YW5jZShwYXJzZWRfcmVzdWx0WydnaXZlX2NvaW4nXSwgYm9vbCkKCQlwcmludChwYXJzZWRfcmVzdWx0WydnaXZlX2NvaW4nXSkKCQlzZWxmLmhhdmVfY29pbiA9IG5vdCBwYXJzZWRfcmVzdWx0WydnaXZlX2NvaW4nXQoKCUBnbC5wdWJsaWMudmlldwoJZGVmIGdldF9oYXZlX2NvaW4oc2VsZikgLT4gYm9vbDoKCQlwcmludChzZWxmLmhhdmVfY29pbikKCQlyZXR1cm4gc2VsZi5oYXZlX2NvaW4KFaMC4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhecAAAAAgwIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/semi-stable/llm/woc.0_0.hash b/tests/cases/semi-stable/llm/woc.0_0.hash new file mode 100644 index 000000000..911179dae --- /dev/null +++ b/tests/cases/semi-stable/llm/woc.0_0.hash @@ -0,0 +1 @@ +LQEQAAUF diff --git a/tests/cases/semi-stable/llm/woc.0_0_0_0.hash b/tests/cases/semi-stable/llm/woc.0_0_0_0.hash new file mode 100644 index 000000000..911179dae --- /dev/null +++ b/tests/cases/semi-stable/llm/woc.0_0_0_0.hash @@ -0,0 +1 @@ +LQEQAAUF diff --git a/tests/cases/semi-stable/web/file_schema_web_bash.0.hash b/tests/cases/semi-stable/web/file_schema_web_bash.0.hash new file mode 100644 index 000000000..a012d3ff4 --- /dev/null +++ b/tests/cases/semi-stable/web/file_schema_web_bash.0.hash @@ -0,0 +1 @@ +LRFcZXhpdF9jb2RlIDEAHRWjAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowIhueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALoAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYnoV50UNnwTpw9jS2Fao6ceN+gCB6iwSj9yTzi3zXr1gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDEgcBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZiwgcGF0aDogc3RyKToKCQlkZWYgbm9uZGV0KCk6CgkJCXByaW50KGdsLm5vbmRldC53ZWIucmVuZGVyKHBhdGgsIG1vZGU9J3RleHQnKSkKCgkJZ2wuZXFfcHJpbmNpcGxlLnN0cmljdF9lcShub25kZXQpCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/semi-stable/web/file_schema_web_proc.0.hash b/tests/cases/semi-stable/web/file_schema_web_proc.0.hash new file mode 100644 index 000000000..a012d3ff4 --- /dev/null +++ b/tests/cases/semi-stable/web/file_schema_web_proc.0.hash @@ -0,0 +1 @@ +LRFcZXhpdF9jb2RlIDEAHRWjAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowIhueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALoAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYnoV50UNnwTpw9jS2Fao6ceN+gCB6iwSj9yTzi3zXr1gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDEgcBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZiwgcGF0aDogc3RyKToKCQlkZWYgbm9uZGV0KCk6CgkJCXByaW50KGdsLm5vbmRldC53ZWIucmVuZGVyKHBhdGgsIG1vZGU9J3RleHQnKSkKCgkJZ2wuZXFfcHJpbmNpcGxlLnN0cmljdF9lcShub25kZXQpCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/semi-stable/web/request_signed.0.hash b/tests/cases/semi-stable/web/request_signed.0.hash new file mode 100644 index 000000000..61063fd76 --- /dev/null +++ b/tests/cases/semi-stable/web/request_signed.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyD1AQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJZGVmIF9faW5pdF9fKHNlbGYpOgoJCWRlZiBydW4oKToKCQkJYm9keSA9IGInXHhkZVx4YWRceGJlXHhlZicKCQkJcmVzID0gZ2wubm9uZGV0LndlYi5wb3N0KAoJCQkJJ2h0dHBzOi8vdGVzdC1zZXJ2ZXIuZ2VubGF5ZXIuY29tL2JvZHkvZWNoby1zaWduZWQnLAoJCQkJYm9keT1ib2R5LAoJCQkJaGVhZGVycz17fSwKCQkJCXNpZ249VHJ1ZSwKCQkJKQoJCQlhc3NlcnQgcmVzLnN0YXR1cyA9PSAyMDAsIGYnZXhwZWN0ZWQgc3RhdHVzIDIwMCwgZ290IHtyZXMuc3RhdHVzfScKCQkJYXNzZXJ0IHJlcy5ib2R5ID09IGJvZHksIGYnZXhwZWN0ZWQgYm9keSB7Ym9keSFyfSwgZ290IHtyZXMuYm9keSFyfScKCQkJcmV0dXJuIHJlcy5ib2R5CgoJCXByaW50KGdsLmVxX3ByaW5jaXBsZS5zdHJpY3RfZXEocnVuKSkKAAAAAAAAAAU= diff --git a/tests/cases/stable/agentic/wasi/environ_args/environ_args.0.hash b/tests/cases/stable/agentic/wasi/environ_args/environ_args.0.hash new file mode 100644 index 000000000..7cc3e93a3 --- /dev/null +++ b/tests/cases/stable/agentic/wasi/environ_args/environ_args.0.hash @@ -0,0 +1 @@ +LQmVAbQBZW52X1BZVEhPTkhPTUU9L3B5L3N0ZPwBZW52X1BZVEhPTlBBVEg9L3B5L3N0ZDovcHkvbGlic0xlbnZfcHdkPS/sAnN5c19hcmd2PVsnL3B5L2xpYnMvX2dlbmxheWVyX2Jvb3Rsb2FkZXIucHknXZwBc3lzX3BhdGhfMD0vcHkvbGlic5QBc3lzX3BhdGhfMT0vcHkvc3RknAFzeXNfcGF0aF8yPS9weS9saWJzpAJzeXNfcGF0aF8zPS9weS9zdGQvbGliL3B5dGhvbjMxMy56aXCMAnN5c19wYXRoXzQ9L3B5L3N0ZC9saWIvcHl0aG9uMy4xM+wCc3lzX3BhdGhfNT0vcHkvc3RkL2xpYi9weXRob24zLjEzL2xpYi1keW5sb2FkZHN5c19wYXRoXzY9L4wBc3lzX3BsYXRmb3JtPXdhc2mMCHN5c192ZXJzaW9uPTMuMTMuMSAobWFpbiwgSmFuXzI0XzIwMjQsIDAwOjQyOjQyKSBbQ2xhbmcgMjIuMS4wLXdhc2ktc2RrIChodHRwczovL2dpdGh1Yi5jb20vbGx2bS9sbHZtLXByb2plY3QgNDQzNGRhYmI2OTkxNjg1NmI4MqQBc3lzX2J5dGVvcmRlcj1saXR0bGW0AXN5c19tYXhzaXplPTIxNDc0ODM2NDdsb3NfbmFtZT1wb3NpeERvc19jd2Q9L0xvc19waWQ9NDIAHRWjAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowIhueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALoAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYnoV50UNnwTpw9jS2Fao6ceN+gCB6iwSj9yTzi3zXr1gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDOGIDAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKaW1wb3J0IG9zCmltcG9ydCBzeXMKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcmVzOiBsaXN0W3N0cl0gPSBbXQoKCQllbnZfdmFycyA9IGRpY3Qob3MuZW52aXJvbikKCQlmb3IgayBpbiBzb3J0ZWQoZW52X3ZhcnMua2V5cygpKToKCQkJcmVzLmFwcGVuZChmJ2Vudl97a309e2Vudl92YXJzW2tdfScpCgoJCXJlcy5hcHBlbmQoZidzeXNfYXJndj17c3lzLmFyZ3Z9JykKCgkJZm9yIGksIHAgaW4gZW51bWVyYXRlKHN5cy5wYXRoKToKCQkJcmVzLmFwcGVuZChmJ3N5c19wYXRoX3tpfT17cH0nKQoKCQlyZXMuYXBwZW5kKGYnc3lzX3BsYXRmb3JtPXtzeXMucGxhdGZvcm19JykKCQlyZXMuYXBwZW5kKGYnc3lzX3ZlcnNpb249e3N5cy52ZXJzaW9ufScpCgkJcmVzLmFwcGVuZChmJ3N5c19ieXRlb3JkZXI9e3N5cy5ieXRlb3JkZXJ9JykKCQlyZXMuYXBwZW5kKGYnc3lzX21heHNpemU9e3N5cy5tYXhzaXplfScpCgkJcmVzLmFwcGVuZChmJ29zX25hbWU9e29zLm5hbWV9JykKCgkJdHJ5OgoJCQljd2QgPSBvcy5nZXRjd2QoKQoJCQlyZXMuYXBwZW5kKGYnb3NfY3dkPXtjd2R9JykKCQlleGNlcHQgRXhjZXB0aW9uIGFzIGU6CgkJCXJlcy5hcHBlbmQoZidvc19jd2RfZXJyb3I9e2V9JykKCgkJdHJ5OgoJCQlwaWQgPSBvcy5nZXRwaWQoKQoJCQlyZXMuYXBwZW5kKGYnb3NfcGlkPXtwaWR9JykKCQlleGNlcHQgRXhjZXB0aW9uIGFzIGU6CgkJCXJlcy5hcHBlbmQoZidvc19waWRfZXJyb3I9e2V9JykKCgkJZ2wudm0uVXNlckVycm9yLmltbWVkaWF0ZShyZXMpCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/agentic/wasi/hash_random/hash_random.0.hash b/tests/cases/stable/agentic/wasi/hash_random/hash_random.0.hash new file mode 100644 index 000000000..de47d960d --- /dev/null +++ b/tests/cases/stable/agentic/wasi/hash_random/hash_random.0.hash @@ -0,0 +1 @@ +LQmlAbQBUFlUSE9OSEFTSFNFRUQ9Tk9UX1NFVKwBaGFzaF9oZWxsbz0xNjc0OTI3Mzk2pAFoYXNoX3dvcmxkPTU4MzI2NDQ5OJwBaGFzaF90ZXN0PTIwNTg3Mzg5NDxoYXNoXz0wlAFoYXNoX2E9LTIxMjQyMDM4NjDUAWhhc2hfZGV0ZXJtaW5pc209MTk0NzMyODYw9AFoYXNoX2J5dGVzX2InaGVsbG8nPTE2NzQ5MjczOTbkAWhhc2hfYnl0ZXNfYid0ZXN0Jz0yMDU4NzM4OTSEAWhhc2hfYnl0ZXNfYicnPTCsAWhhc2hfdHVwbGU9MTI5MTc5ODYyONQBaGFzaF9mcm96ZW5zZXQ9LTIwMjEzODQwMDhkaGFzaF9pbnRfMD0wZGhhc2hfaW50XzE9MXRoYXNoX2ludF8tMT0tMnRoYXNoX2ludF80Mj00MvQBaGFzaF9pbnRfOTIyMzM3MjAzNjg1NDc3NTgwOD0ylAFoYXNoX2FsZ29yaXRobT1mbnZkaGFzaF9iaXRzPTMyjAFoYXNoX3NlZWRfYml0cz02NAAdFaMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAiG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmAAAAAIMKBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZiehXnRQ2fBOnD2NLYVqjpx436AIHqLBKP3JPOLfNevWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAroAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELAAAAAIM8vAMAACMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CmltcG9ydCBnZW5sYXllciBhcyBnbAppbXBvcnQgc3lzCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJZGVmIF9faW5pdF9fKHNlbGYpOgoJCXJlczogbGlzdFtzdHJdID0gW10KCgkJdHJ5OgoJCQlpbXBvcnQgb3MKCgkJCXNlZWQgPSBvcy5lbnZpcm9uLmdldCgnUFlUSE9OSEFTSFNFRUQnLCAnTk9UX1NFVCcpCgkJCXJlcy5hcHBlbmQoZidQWVRIT05IQVNIU0VFRD17c2VlZH0nKQoJCWV4Y2VwdCBFeGNlcHRpb24gYXMgZToKCQkJcmVzLmFwcGVuZChmJ1BZVEhPTkhBU0hTRUVEX2Vycm9yPXtlfScpCgoJCWZvciBzIGluIFsnaGVsbG8nLCAnd29ybGQnLCAndGVzdCcsICcnLCAnYScsICdkZXRlcm1pbmlzbSddOgoJCQloID0gaGFzaChzKQoJCQlyZXMuYXBwZW5kKGYnaGFzaF97c309e2h9JykKCgkJZm9yIGIgaW4gW2InaGVsbG8nLCBiJ3Rlc3QnLCBiJyddOgoJCQloID0gaGFzaChiKQoJCQlyZXMuYXBwZW5kKGYnaGFzaF9ieXRlc197Yn09e2h9JykKCgkJaCA9IGhhc2goKDEsIDIsICdoZWxsbycpKQoJCXJlcy5hcHBlbmQoZidoYXNoX3R1cGxlPXtofScpCgoJCWggPSBoYXNoKGZyb3plbnNldChbMSwgMiwgM10pKQoJCXJlcy5hcHBlbmQoZidoYXNoX2Zyb3plbnNldD17aH0nKQoKCQlmb3IgaSBpbiBbMCwgMSwgLTEsIDQyLCAyKio2M106CgkJCWggPSBoYXNoKGkpCgkJCXJlcy5hcHBlbmQoZidoYXNoX2ludF97aX09e2h9JykKCgkJcmVzLmFwcGVuZChmJ2hhc2hfYWxnb3JpdGhtPXtzeXMuaGFzaF9pbmZvLmFsZ29yaXRobX0nKQoJCXJlcy5hcHBlbmQoZidoYXNoX2JpdHM9e3N5cy5oYXNoX2luZm8uaGFzaF9iaXRzfScpCgkJcmVzLmFwcGVuZChmJ2hhc2hfc2VlZF9iaXRzPXtzeXMuaGFzaF9pbmZvLnNlZWRfYml0c30nKQoKCQlnbC52bS5Vc2VyRXJyb3IuaW1tZWRpYXRlKHJlcykKBQ== diff --git a/tests/cases/stable/agentic/wasi/set_order/set_order.0.hash b/tests/cases/stable/agentic/wasi/set_order/set_order.0.hash new file mode 100644 index 000000000..1ff69db3d --- /dev/null +++ b/tests/cases/stable/agentic/wasi/set_order/set_order.0.hash @@ -0,0 +1 @@ +LQlN7ARzZXRfb3JkZXI9WydncmFwZScsICdmaWcnLCAnY2hlcnJ5JywgJ2RhdGUnLCAnYXBwbGUnLCAnZWxkZXJiZXJyeScsICdiYW5hbmEnXYwFZGljdF9mcm9tX3NldD1bJ2dyYXBlJywgJ2ZpZycsICdjaGVycnknLCAnZGF0ZScsICdhcHBsZScsICdlbGRlcmJlcnJ5JywgJ2JhbmFuYSddxANmcm96ZW5zZXRfcmVwcj1mcm96ZW5zZXQoeydhJywgJ2InLCAneScsICd4JywgJ3onLCAndyd9KfQCc2V0X3VuaW9uX29yZGVyPVsnZScsICdkJywgJ2YnLCAnYScsICdjJywgJ2InXdQBc2V0X2ludGVyX29yZGVyPVsnZCcsICdjJ13MAXNldF9kaWZmX29yZGVyPVsnYScsICdiJ138B2JpZ19zZXRfZmlyc3RfMTA9WydpdGVtXzM4JywgJ2l0ZW1fMzknLCAnaXRlbV8xOCcsICdpdGVtXzE5JywgJ2l0ZW1fMTYnLCAnaXRlbV8xNycsICdpdGVtXzE0JywgJ2l0ZW1fMTUnLCAnaXRlbV8xMicsICdpdGVtXzEzJ128AWJpZ19zZXRfaGFzaD0xOTcwNTYwODI57A1kaWN0X2tleXNfYWZ0ZXJfbXV0YXRpb25zPVsna2V5XzEnLCAna2V5XzMnLCAna2V5XzUnLCAna2V5XzcnLCAna2V5XzknLCAna2V5XzExJywgJ2tleV8xMycsICdrZXlfMTUnLCAna2V5XzE3JywgJ2tleV8xOScsICdrZXlfMjAnLCAna2V5XzIxJywgJ2tleV8yMicsICdrZXlfMjMnLCAna2V5XzI0JywgJ2tleV8yNScsICdrZXlfMjYnLCAna2V5XzI3JywgJ2tleV8yOCcsICdrZXlfMjknXQAdFaMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAiG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmAAAAAIMKBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZiehXnRQ2fBOnD2NLYVqjpx436AIHqLBKP3JPOLfNevWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAroAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELAAAAAINIaAQAACMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CmltcG9ydCBnZW5sYXllciBhcyBnbAoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlyZXM6IGxpc3Rbc3RyXSA9IFtdCgoJCXMgPSB7J2FwcGxlJywgJ2JhbmFuYScsICdjaGVycnknLCAnZGF0ZScsICdlbGRlcmJlcnJ5JywgJ2ZpZycsICdncmFwZSd9CgkJb3JkZXIgPSBsaXN0KHMpCgkJcmVzLmFwcGVuZChmJ3NldF9vcmRlcj17b3JkZXJ9JykKCgkJZCA9IHtrOiBpIGZvciBpLCBrIGluIGVudW1lcmF0ZShzKX0KCQlyZXMuYXBwZW5kKGYnZGljdF9mcm9tX3NldD17bGlzdChkLmtleXMoKSl9JykKCgkJZnMgPSBmcm96ZW5zZXQoWyd4JywgJ3knLCAneicsICd3JywgJ2EnLCAnYiddKQoJCXJlcy5hcHBlbmQoZidmcm96ZW5zZXRfcmVwcj17cmVwcihmcyl9JykKCgkJczEgPSB7J2EnLCAnYicsICdjJywgJ2QnfQoJCXMyID0geydjJywgJ2QnLCAnZScsICdmJ30KCQl1bmlvbiA9IGxpc3QoczEgfCBzMikKCQlyZXMuYXBwZW5kKGYnc2V0X3VuaW9uX29yZGVyPXt1bmlvbn0nKQoJCWludGVyID0gbGlzdChzMSAmIHMyKQoJCXJlcy5hcHBlbmQoZidzZXRfaW50ZXJfb3JkZXI9e2ludGVyfScpCgkJZGlmZiA9IGxpc3QoczEgLSBzMikKCQlyZXMuYXBwZW5kKGYnc2V0X2RpZmZfb3JkZXI9e2RpZmZ9JykKCgkJYmlnX3NldCA9IHtmJ2l0ZW1fe2l9JyBmb3IgaSBpbiByYW5nZSg1MCl9CgkJYmlnX29yZGVyID0gbGlzdChiaWdfc2V0KQoJCXJlcy5hcHBlbmQoZidiaWdfc2V0X2ZpcnN0XzEwPXtiaWdfb3JkZXJbOjEwXX0nKQoJCXJlcy5hcHBlbmQoZidiaWdfc2V0X2hhc2g9e2hhc2goZnJvemVuc2V0KGJpZ19zZXQpKX0nKQoKCQlkMiA9IHt9CgkJZm9yIGkgaW4gcmFuZ2UoMjApOgoJCQlkMltmJ2tleV97aX0nXSA9IGkKCQlmb3IgaSBpbiByYW5nZSgwLCAyMCwgMik6CgkJCWRlbCBkMltmJ2tleV97aX0nXQoJCWZvciBpIGluIHJhbmdlKDIwLCAzMCk6CgkJCWQyW2Yna2V5X3tpfSddID0gaQoJCXJlcy5hcHBlbmQoZidkaWN0X2tleXNfYWZ0ZXJfbXV0YXRpb25zPXtsaXN0KGQyLmtleXMoKSl9JykKCgkJZ2wudm0uVXNlckVycm9yLmltbWVkaWF0ZShyZXMpCgAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/agentic/wasi/wasi_clock/wasi_clock.0.hash b/tests/cases/stable/agentic/wasi/wasi_clock/wasi_clock.0.hash new file mode 100644 index 000000000..40ba34c50 --- /dev/null +++ b/tests/cases/stable/agentic/wasi/wasi_clock/wasi_clock.0.hash @@ -0,0 +1 @@ +LQlF3AF0aW1lX3RpbWU9MTczMjYwMzM2Mi40MjQyNDLcAXRpbWVfbnM9MTczMjYwMzM2MjQyNDI0MjAwMNwBbW9ub3RvbmljPTE3MzI2MDMzNjIuNDI0MjQyhAJtb25vdG9uaWNfbnM9MTczMjYwMzM2MjQyNDI0MjAwMPQBcGVyZl9jb3VudGVyPTE3MzI2MDMzNjIuNDI0MjQyhAFwcm9jZXNzX3RpbWU9MC4w9AJjbG9ja19nZXR0aW1lX0NMT0NLX1JFQUxUSU1FPTE3MzI2MDMzNjIuNDI0MjQy/AJjbG9ja19nZXR0aW1lX0NMT0NLX01PTk9UT05JQz0xNzMyNjAzMzYyLjQyNDI0MgAdFaMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAiG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmAAAAAIMKBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZiehXnRQ2fBOnD2NLYVqjpx436AIHqLBKP3JPOLfNevWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAroAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELAAAAAINOyQQAACMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CmltcG9ydCBnZW5sYXllciBhcyBnbAppbXBvcnQgdGltZQoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlyZXM6IGxpc3Rbc3RyXSA9IFtdCgoJCXQgPSB0aW1lLnRpbWUoKQoJCXJlcy5hcHBlbmQoZid0aW1lX3RpbWU9e3R9JykKCgkJdF9ucyA9IHRpbWUudGltZV9ucygpCgkJcmVzLmFwcGVuZChmJ3RpbWVfbnM9e3RfbnN9JykKCgkJdHJ5OgoJCQltID0gdGltZS5tb25vdG9uaWMoKQoJCQlyZXMuYXBwZW5kKGYnbW9ub3RvbmljPXttfScpCgkJZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgoJCQlyZXMuYXBwZW5kKGYnbW9ub3RvbmljX2Vycm9yPXtlfScpCgoJCXRyeToKCQkJbV9ucyA9IHRpbWUubW9ub3RvbmljX25zKCkKCQkJcmVzLmFwcGVuZChmJ21vbm90b25pY19ucz17bV9uc30nKQoJCWV4Y2VwdCBFeGNlcHRpb24gYXMgZToKCQkJcmVzLmFwcGVuZChmJ21vbm90b25pY19uc19lcnJvcj17ZX0nKQoKCQl0cnk6CgkJCXAgPSB0aW1lLnBlcmZfY291bnRlcigpCgkJCXJlcy5hcHBlbmQoZidwZXJmX2NvdW50ZXI9e3B9JykKCQlleGNlcHQgRXhjZXB0aW9uIGFzIGU6CgkJCXJlcy5hcHBlbmQoZidwZXJmX2NvdW50ZXJfZXJyb3I9e2V9JykKCgkJdHJ5OgoJCQlwdCA9IHRpbWUucHJvY2Vzc190aW1lKCkKCQkJcmVzLmFwcGVuZChmJ3Byb2Nlc3NfdGltZT17cHR9JykKCQlleGNlcHQgRXhjZXB0aW9uIGFzIGU6CgkJCXJlcy5hcHBlbmQoZidwcm9jZXNzX3RpbWVfZXJyb3I9e2V9JykKCgkJZm9yIGNsb2NrX2lkX25hbWUgaW4gWwoJCQknQ0xPQ0tfUkVBTFRJTUUnLAoJCQknQ0xPQ0tfTU9OT1RPTklDJywKCQkJJ0NMT0NLX1BST0NFU1NfQ1BVVElNRV9JRCcsCgkJCSdDTE9DS19USFJFQURfQ1BVVElNRV9JRCcsCgkJXToKCQkJdHJ5OgoJCQkJY2lkID0gZ2V0YXR0cih0aW1lLCBjbG9ja19pZF9uYW1lLCBOb25lKQoJCQkJaWYgY2lkIGlzIG5vdCBOb25lOgoJCQkJCXZhbCA9IHRpbWUuY2xvY2tfZ2V0dGltZShjaWQpCgkJCQkJcmVzLmFwcGVuZChmJ2Nsb2NrX2dldHRpbWVfe2Nsb2NrX2lkX25hbWV9PXt2YWx9JykKCQkJZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgoJCQkJcmVzLmFwcGVuZChmJ2Nsb2NrX2dldHRpbWVfe2Nsb2NrX2lkX25hbWV9X2Vycm9yPXtlfScpCgoJCWdsLnZtLlVzZXJFcnJvci5pbW1lZGlhdGUocmVzKQoAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/agentic/wasi/wasi_random/wasi_random.0.hash b/tests/cases/stable/agentic/wasi/wasi_random/wasi_random.0.hash new file mode 100644 index 000000000..c5496980c --- /dev/null +++ b/tests/cases/stable/agentic/wasi/wasi_random/wasi_random.0.hash @@ -0,0 +1 @@ +LQlF5AJ1cmFuZG9tX2hleD0yYzkyNzNjNWMwYWRjYWFmODRhNjIwMTdlNWZiZWYyZfwBcmFuZG9tX2ludD0xMzg1OTU0MTY4OTc0MzkxMzUwMvwBcmFuZG9tX2Zsb2F0PTAuNTY4OTk2NjA3NzA4ODQ0OfQBdXJhbmRvbV9zZXFfMD02MzcxMTg0ZDYxOTVkY2U49AF1cmFuZG9tX3NlcV8xPTI1OWRlNWIzMjkwMWU2MDb0AXVyYW5kb21fc2VxXzI9ZDhlNWNiOWYwNTU4YzI4Y/QBdXJhbmRvbV9zZXFfMz1lMzg3OTliYTc4ZjA5Mjk19AF1cmFuZG9tX3NlcV80PWYwNmU1MDY3YTQyOWYyZTQAHRWjAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowIhueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALoAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYnoV50UNnwTpw9jS2Fao6ceN+gCB6iwSj9yTzi3zXr1gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDIPABAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKaW1wb3J0IG9zCmltcG9ydCByYW5kb20KCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcmVzOiBsaXN0W3N0cl0gPSBbXQoKCQlyYW5kX2J5dGVzID0gb3MudXJhbmRvbSgxNikKCQlyZXMuYXBwZW5kKGYndXJhbmRvbV9oZXg9e3JhbmRfYnl0ZXMuaGV4KCl9JykKCgkJdmFsID0gcmFuZG9tLnJhbmRpbnQoMCwgMioqNjQpCgkJcmVzLmFwcGVuZChmJ3JhbmRvbV9pbnQ9e3ZhbH0nKQoKCQl2YWwyID0gcmFuZG9tLnJhbmRvbSgpCgkJcmVzLmFwcGVuZChmJ3JhbmRvbV9mbG9hdD17dmFsMn0nKQoKCQlmb3IgaSBpbiByYW5nZSg1KToKCQkJYiA9IG9zLnVyYW5kb20oOCkKCQkJcmVzLmFwcGVuZChmJ3VyYW5kb21fc2VxX3tpfT17Yi5oZXgoKX0nKQoKCQlnbC52bS5Vc2VyRXJyb3IuaW1tZWRpYXRlKHJlcykKAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/exploits/call_wasi_extra.0.hash b/tests/cases/stable/exploits/call_wasi_extra.0.hash new file mode 100644 index 000000000..6385750eb --- /dev/null +++ b/tests/cases/stable/exploits/call_wasi_extra.0.hash @@ -0,0 +1 @@ +LRFkZXhpdF9jb2RlIDMwABUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxynAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCmltcG9ydCBfZ2VubGF5ZXJfd2FzaSBhcyB3YXNpCmltcG9ydCBnZW5sYXllci5jYWxsZGF0YSBhcyBjYWxsZGF0YQppbXBvcnQgb3MKCmltcG9ydCBjbG91ZHBpY2tsZQoKCmRlZiBmb28oKToKCXByaW50KCd3ZSB3aWxsIGhhdmUgYW4gaW5maW5pdGUgbG9vcC4uLicpCgoKdHJ5OgoJZmQgPSB3YXNpLmdsX2NhbGwoCgkJY2FsbGRhdGEuZW5jb2RlKAoJCQl7CgkJCQknU2FuZGJveCc6IHsKCQkJCQknYV9leHRyYV9maWVsZCc6IFRydWUsCgkJCQkJJ2RhdGEnOiBjbG91ZHBpY2tsZS5kdW1wcyhmb28pLAoJCQkJfQoJCQl9CgkJKSwKCSkKZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgoJcHJpbnQoZSkKCWV4aXQoMzApCgpwcmludChvcy5mZG9wZW4oZmQpLnJlYWQoKSkKCmV4aXQoMCkKAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/exploits/close_std.0.hash b/tests/cases/stable/exploits/close_std.0.hash new file mode 100644 index 000000000..5f7fca66a --- /dev/null +++ b/tests/cases/stable/exploits/close_std.0.hash @@ -0,0 +1 @@ +LQEAABUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgwhwAAAAAGFzbQEAAAABCQJgAABgAX8BfwIjARZ3YXNpX3NuYXBzaG90X3ByZXZpZXcxCGZkX2Nsb3NlAAEDAgEABQMBAAEHEwIGX3N0YXJ0AAEGbWVtb3J5AgAKGAEWAEEAEAAaQQEQABpBAhAAGkEDEAAaCwAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/exploits/deep_calldata.0.hash b/tests/cases/stable/exploits/deep_calldata.0.hash new file mode 100644 index 000000000..d66389abb --- /dev/null +++ b/tests/cases/stable/exploits/deep_calldata.0.hash @@ -0,0 +1 @@ +LRGEAndhc21fdHJhcCBVbnJlYWNoYWJsZUNvZGVSZWFjaGVkABUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgwy2AAAAAGFzbQEAAAABCwJgA39/fwF/YAAAAhgBDGdlbmxheWVyX3NkawdnbF9jYWxsAAADAgEBBQMBAAEGBgF/AEEQCwcTAgZtZW1vcnkCAAZfc3RhcnQAAQpOAUwBBH8jAEEBa0AAGiMAQRB0IQIgAkEEayEDQQghAEGNmrToACEBAkADQCAAIANPDQEgACABNgIAIABBBGohAAwACwtBACACIAMQAAALCw8BAEEACwkOBlJldHVybg0AAAAAAAAF diff --git a/tests/cases/stable/exploits/disagree_in_sandbox.0.hash b/tests/cases/stable/exploits/disagree_in_sandbox.0.hash new file mode 100644 index 000000000..bfd2b8b41 --- /dev/null +++ b/tests/cases/stable/exploits/disagree_in_sandbox.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxZXAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJZGVmIGZuKCk6CgkJCXRyeToKCQkJCWdsLnZtLnJ1bl9ub25kZXRfZGVmYXVsdChsYW1iZGE6IE5vbmUsIGxhbWJkYSB4OiBGYWxzZSkKCQkJZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgoJCQkJcHJpbnQoZSkKCgkJcHJpbnQoJ3ByZSBzcGF3bicpCgkJcmVzID0gZ2wudm0uc3Bhd25fc2FuZGJveChmbikKCQlwcmludChmJ3Jlcz17cmVzfScpCgAAAAAABQ== diff --git a/tests/cases/stable/exploits/flt.0.hash b/tests/cases/stable/exploits/flt.0.hash new file mode 100644 index 000000000..2268cf101 --- /dev/null +++ b/tests/cases/stable/exploits/flt.0.hash @@ -0,0 +1 @@ +LRHcAXdhc21fdHJhcCBEZXRlcm1pbmlzdGljTW9kZQAVFaMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAroAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELAAAAAIMMsgAAAABhc20BAAAAAQ0DYAAAYAF/AGABfAF8AiQBFndhc2lfc25hcHNob3RfcHJldmlldzEJcHJvY19leGl0AAEDAwICAAUEAQCBAgcTAgZfc3RhcnQAAgZtZW1vcnkCAApTAjwBAXxEAAAAAAAA8D8hAQJAIABEAAAAAAAAAABlDQAgAEQAAAAAAADgv6AQAUTNzMzMzMz0P6IhAQsgAQsUAEQAAAAAAAAAQBABqkECaxAAAAsAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/exploits/fork_bomb.0.hash b/tests/cases/stable/exploits/fork_bomb.0.hash new file mode 100644 index 000000000..98d66b93c --- /dev/null +++ b/tests/cases/stable/exploits/fork_bomb.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxIFAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpkZWYgYm9tYigpOgoJcmVzID0gZ2wudm0uc3Bhd25fc2FuZGJveChib21iKQoJaWYgaXNpbnN0YW5jZShyZXMsIGdsLnZtLlZNRXJyb3IpOgoJCXByaW50KHJlcy5tZXNzYWdlKQoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlib21iKCkKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/exploits/method_init.0.hash b/tests/cases/stable/exploits/method_init.0.hash new file mode 100644 index 000000000..5a3f58162 --- /dev/null +++ b/tests/cases/stable/exploits/method_init.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyh8AgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcHJpbnQoJ2luaXQnKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBwdWIoc2VsZik6CgkJZXZhbCgicHJpbnQoJ2luaXQgZnJvbSBwdWIhJykiKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiByYmFjayhzZWxmKToKCQlnbC52bS5Vc2VyRXJyb3IuaW1tZWRpYXRlKCJuYWgsIEkgd29uJ3QgZXhlY3V0ZSIpCgoJZGVmIHByaXYoc2VsZik6CgkJZXZhbCgicHJpbnQoJ2luaXQgZnJvbSBwcml2IScpIikKCglAZ2wucHVibGljLndyaXRlCglkZWYgcmV0bihzZWxmKToKCQlyZXR1cm4geyd4JzogMTB9CgoJQGdsLnB1YmxpYy52aWV3CglkZWYgcmV0bl92aWV3KHNlbGYpOgoJCXJldHVybiB7J3gnOiAxMH0KCglAZ2wucHVibGljLndyaXRlCglkZWYgZGV0X3Zpb2woc2VsZik6CgkJZ2wubm9uZGV0LndlYi5yZW5kZXIoCgkJCSdodHRwczovL3Rlc3Qtc2VydmVyLmdlbmxheWVyLmNvbS9zdGF0aWMvZ2Vudm0vaGVsbG8uaHRtbCcsCgkJCW1vZGU9J3RleHQnLAoJCSkKBQ== diff --git a/tests/cases/stable/exploits/method_init.0_0.hash b/tests/cases/stable/exploits/method_init.0_0.hash new file mode 100644 index 000000000..131eae252 --- /dev/null +++ b/tests/cases/stable/exploits/method_init.0_0.hash @@ -0,0 +1 @@ +LRFcZXhpdF9jb2RlIDEABQU= diff --git a/tests/cases/stable/exploits/method_private.0.hash b/tests/cases/stable/exploits/method_private.0.hash new file mode 100644 index 000000000..5a3f58162 --- /dev/null +++ b/tests/cases/stable/exploits/method_private.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyh8AgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcHJpbnQoJ2luaXQnKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBwdWIoc2VsZik6CgkJZXZhbCgicHJpbnQoJ2luaXQgZnJvbSBwdWIhJykiKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiByYmFjayhzZWxmKToKCQlnbC52bS5Vc2VyRXJyb3IuaW1tZWRpYXRlKCJuYWgsIEkgd29uJ3QgZXhlY3V0ZSIpCgoJZGVmIHByaXYoc2VsZik6CgkJZXZhbCgicHJpbnQoJ2luaXQgZnJvbSBwcml2IScpIikKCglAZ2wucHVibGljLndyaXRlCglkZWYgcmV0bihzZWxmKToKCQlyZXR1cm4geyd4JzogMTB9CgoJQGdsLnB1YmxpYy52aWV3CglkZWYgcmV0bl92aWV3KHNlbGYpOgoJCXJldHVybiB7J3gnOiAxMH0KCglAZ2wucHVibGljLndyaXRlCglkZWYgZGV0X3Zpb2woc2VsZik6CgkJZ2wubm9uZGV0LndlYi5yZW5kZXIoCgkJCSdodHRwczovL3Rlc3Qtc2VydmVyLmdlbmxheWVyLmNvbS9zdGF0aWMvZ2Vudm0vaGVsbG8uaHRtbCcsCgkJCW1vZGU9J3RleHQnLAoJCSkKBQ== diff --git a/tests/cases/stable/exploits/method_private.0_0.hash b/tests/cases/stable/exploits/method_private.0_0.hash new file mode 100644 index 000000000..131eae252 --- /dev/null +++ b/tests/cases/stable/exploits/method_private.0_0.hash @@ -0,0 +1 @@ +LRFcZXhpdF9jb2RlIDEABQU= diff --git a/tests/cases/stable/exploits/oom.0.hash b/tests/cases/stable/exploits/oom.0.hash new file mode 100644 index 000000000..f93d7a230 --- /dev/null +++ b/tests/cases/stable/exploits/oom.0.hash @@ -0,0 +1 @@ +LRFcZXhpdF9jb2RlIDEAFRWjAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCHUAAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKc3ogPSAxMDI0CmFsbCA9IFtdCndoaWxlIFRydWU6CglwcmludChzeikKCWFsbC5hcHBlbmQobGlzdChyYW5nZShzeikpKQoJc3ogKj0gOAoAAAAAAAAABQ== diff --git a/tests/cases/stable/exploits/rec.0.hash b/tests/cases/stable/exploits/rec.0.hash new file mode 100644 index 000000000..19cd0676f --- /dev/null +++ b/tests/cases/stable/exploits/rec.0.hash @@ -0,0 +1 @@ +LRG8AXdhc21fdHJhcCBTdGFja092ZXJmbG93ABUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgwZEAAAAAGFzbQEAAAABCAJgAABgAAF+AwMCAQAFBAEAgQIHEwIGX3N0YXJ0AAEGbWVtb3J5AgAKEAIIABAAQgF8DwsFABAAAAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/exploits/rec_1023.0.hash b/tests/cases/stable/exploits/rec_1023.0.hash new file mode 100644 index 000000000..ff73df4cc --- /dev/null +++ b/tests/cases/stable/exploits/rec_1023.0.hash @@ -0,0 +1 @@ +LQEAABUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgwZRAAAAAGFzbQEAAAABCAJgAABgAX4AAwMCAQAFBAEAgQIHEwIGX3N0YXJ0AAEGbWVtb3J5AgAKHQISACAAQgBVBEAgAEIBfRAACw8LCABC/gcQAA8LAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/exploits/rec_1024.0.hash b/tests/cases/stable/exploits/rec_1024.0.hash new file mode 100644 index 000000000..0a99e6076 --- /dev/null +++ b/tests/cases/stable/exploits/rec_1024.0.hash @@ -0,0 +1 @@ +LRG8AXdhc21fdHJhcCBTdGFja092ZXJmbG93ABUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgwZRAAAAAGFzbQEAAAABCAJgAABgAX4AAwMCAQAFBAEAgQIHEwIGX3N0YXJ0AAEGbWVtb3J5AgAKHQISACAAQgBVBEAgAEIBfRAACw8LCABC/wcQAAALAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/exploits/storage_page_limit.0.hash b/tests/cases/stable/exploits/storage_page_limit.0.hash new file mode 100644 index 000000000..74a0ea1db --- /dev/null +++ b/tests/cases/stable/exploits/storage_page_limit.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgx7aAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCmltcG9ydCBnZW5sYXllciBhcyBnbAppbXBvcnQgX2dlbmxheWVyX3dhc2kgYXMgd2FzaQoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwYXNzCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIHdyaXRlXzJfcGFnZXMoc2VsZik6CgkJc2xvdCA9IGInXHg0MicgKiAzMgoJCWZvciBpIGluIHJhbmdlKDEwKToKCQkJd2FzaS5zdG9yYWdlX3dyaXRlKHNsb3QsIDAsIGInXHgwMScgKiA2NCkgICMgMiBwYWdlcyAoNjQgYnl0ZXMgLyAzMiBwZXIgcGFnZSkKCglAZ2wucHVibGljLndyaXRlCglkZWYgd3JpdGVfM19wYWdlcyhzZWxmKToKCQlzbG90ID0gYidceDQyJyAqIDMyCgkJd2FzaS5zdG9yYWdlX3dyaXRlKHNsb3QsIDAsIGInXHgwMScgKiA5NikgICMgMyBwYWdlcyAoOTYgYnl0ZXMgLyAzMiBwZXIgcGFnZSkKAAAF diff --git a/tests/cases/stable/exploits/storage_page_limit.0_0.hash b/tests/cases/stable/exploits/storage_page_limit.0_0.hash new file mode 100644 index 000000000..f553141ac --- /dev/null +++ b/tests/cases/stable/exploits/storage_page_limit.0_0.hash @@ -0,0 +1 @@ +LQEAAA0VowJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQgAAAACDBAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEF diff --git a/tests/cases/stable/exploits/storage_page_limit.0_1.hash b/tests/cases/stable/exploits/storage_page_limit.0_1.hash new file mode 100644 index 000000000..d4bb38342 --- /dev/null +++ b/tests/cases/stable/exploits/storage_page_limit.0_1.hash @@ -0,0 +1 @@ +LRFcT09NIHN0b3JhZ2UADRWjAkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCAAAAAIMEAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQU= diff --git a/tests/cases/stable/exploits/storage_rw_long.0.hash b/tests/cases/stable/exploits/storage_rw_long.0.hash new file mode 100644 index 000000000..86ce267b3 --- /dev/null +++ b/tests/cases/stable/exploits/storage_rw_long.0.hash @@ -0,0 +1 @@ +LRFcZXhpdF9jb2RlIDEAFRWjAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCo8AAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKaW1wb3J0IF9nZW5sYXllcl93YXNpIGFzIHdhc2kKCmJ1ZiA9IGJ5dGVhcnJheSgzKQp3YXNpLnN0b3JhZ2VfcmVhZChiJ1x4MDAnICogMzIsIDIqKjMyIC0gMSwgYnVmKQpleGl0KDApCgAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/exploits/storage_rw_long.0_0.hash b/tests/cases/stable/exploits/storage_rw_long.0_0.hash new file mode 100644 index 000000000..9a0100cb6 --- /dev/null +++ b/tests/cases/stable/exploits/storage_rw_long.0_0.hash @@ -0,0 +1 @@ +LRFcZXhpdF9jb2RlIDEAFRWjAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDCoUAAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKaW1wb3J0IF9nZW5sYXllcl93YXNpIGFzIHdhc2kKCndhc2kuc3RvcmFnZV93cml0ZShiJ1x4MDAnICogMzIsIDIqKjMyIC0gMSwgYidceDAwXHgwMCcpCmV4aXQoMCkKKQpleGl0KDApCgAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/exploits/subtract_on_start_underflow.0.hash b/tests/cases/stable/exploits/subtract_on_start_underflow.0.hash new file mode 100644 index 000000000..7521a6ab0 --- /dev/null +++ b/tests/cases/stable/exploits/subtract_on_start_underflow.0.hash @@ -0,0 +1 @@ +LRHkAU9PTSByZWNlaXB0IG1lc3NhZ2UgaW50ZXJuYWwABQU= diff --git a/tests/cases/stable/exploits/unreachable.0.hash b/tests/cases/stable/exploits/unreachable.0.hash new file mode 100644 index 000000000..b8fe6da06 --- /dev/null +++ b/tests/cases/stable/exploits/unreachable.0.hash @@ -0,0 +1 @@ +LRGEAndhc21fdHJhcCBVbnJlYWNoYWJsZUNvZGVSZWFjaGVkABUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgwQlAAAAAGFzbQEAAAABBAFgAAADAgEABwoBBl9zdGFydAAACgUBAwAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/nondet/leader_errors/empty_leader_result.0.hash b/tests/cases/stable/nondet/leader_errors/empty_leader_result.0.hash new file mode 100644 index 000000000..5e5759390 --- /dev/null +++ b/tests/cases/stable/nondet/leader_errors/empty_leader_result.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyIcAgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgZm9vKHNlbGYpOgoJCWRlZiBkb19mbigpOgoJCQlyYWlzZSBFeGNlcHRpb24oKQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBiYXIoc2VsZik6CgkJZGVmIGRvX2ZuKCk6CgkJCXJldHVybgoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBleChzZWxmKToKCQlkZWYgZG9fZm4oKToKCQkJZXhpdCgyKQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBleDIoc2VsZik6CgkJZGVmIGRvX2ZuKCk6CgkJCW5vbl9leGlzdGVudF9mbigpICAjIG5vcWEKCgkJZ2wuZXFfcHJpbmNpcGxlLnN0cmljdF9lcShkb19mbikKBQ== diff --git a/tests/cases/stable/nondet/leader_errors/empty_leader_result.0_0.hash b/tests/cases/stable/nondet/leader_errors/empty_leader_result.0_0.hash new file mode 100644 index 000000000..e031a6c8c --- /dev/null +++ b/tests/cases/stable/nondet/leader_errors/empty_leader_result.0_0.hash @@ -0,0 +1 @@ +LRHcAWFic2VudF9sZWFkZXJfbm9uZGV0X291dHB1dAAFBQ== diff --git a/tests/cases/stable/nondet/leader_errors/leader_no_nondet.0.hash b/tests/cases/stable/nondet/leader_errors/leader_no_nondet.0.hash new file mode 100644 index 000000000..5e5759390 --- /dev/null +++ b/tests/cases/stable/nondet/leader_errors/leader_no_nondet.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyIcAgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgZm9vKHNlbGYpOgoJCWRlZiBkb19mbigpOgoJCQlyYWlzZSBFeGNlcHRpb24oKQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBiYXIoc2VsZik6CgkJZGVmIGRvX2ZuKCk6CgkJCXJldHVybgoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBleChzZWxmKToKCQlkZWYgZG9fZm4oKToKCQkJZXhpdCgyKQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBleDIoc2VsZik6CgkJZGVmIGRvX2ZuKCk6CgkJCW5vbl9leGlzdGVudF9mbigpICAjIG5vcWEKCgkJZ2wuZXFfcHJpbmNpcGxlLnN0cmljdF9lcShkb19mbikKBQ== diff --git a/tests/cases/stable/nondet/leader_errors/leader_no_nondet.0_0.hash b/tests/cases/stable/nondet/leader_errors/leader_no_nondet.0_0.hash new file mode 100644 index 000000000..e031a6c8c --- /dev/null +++ b/tests/cases/stable/nondet/leader_errors/leader_no_nondet.0_0.hash @@ -0,0 +1 @@ +LRHcAWFic2VudF9sZWFkZXJfbm9uZGV0X291dHB1dAAFBQ== diff --git a/tests/cases/stable/nondet/leader_errors/simple_leader.0.hash b/tests/cases/stable/nondet/leader_errors/simple_leader.0.hash new file mode 100644 index 000000000..5e5759390 --- /dev/null +++ b/tests/cases/stable/nondet/leader_errors/simple_leader.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyIcAgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgZm9vKHNlbGYpOgoJCWRlZiBkb19mbigpOgoJCQlyYWlzZSBFeGNlcHRpb24oKQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBiYXIoc2VsZik6CgkJZGVmIGRvX2ZuKCk6CgkJCXJldHVybgoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBleChzZWxmKToKCQlkZWYgZG9fZm4oKToKCQkJZXhpdCgyKQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBleDIoc2VsZik6CgkJZGVmIGRvX2ZuKCk6CgkJCW5vbl9leGlzdGVudF9mbigpICAjIG5vcWEKCgkJZ2wuZXFfcHJpbmNpcGxlLnN0cmljdF9lcShkb19mbikKBQ== diff --git a/tests/cases/stable/nondet/leader_errors/simple_leader.0_0.hash b/tests/cases/stable/nondet/leader_errors/simple_leader.0_0.hash new file mode 100644 index 000000000..131eae252 --- /dev/null +++ b/tests/cases/stable/nondet/leader_errors/simple_leader.0_0.hash @@ -0,0 +1 @@ +LRFcZXhpdF9jb2RlIDEABQU= diff --git a/tests/cases/stable/nondet/leader_errors/simple_valid_err_err.0.hash b/tests/cases/stable/nondet/leader_errors/simple_valid_err_err.0.hash new file mode 100644 index 000000000..5e5759390 --- /dev/null +++ b/tests/cases/stable/nondet/leader_errors/simple_valid_err_err.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyIcAgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgZm9vKHNlbGYpOgoJCWRlZiBkb19mbigpOgoJCQlyYWlzZSBFeGNlcHRpb24oKQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBiYXIoc2VsZik6CgkJZGVmIGRvX2ZuKCk6CgkJCXJldHVybgoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBleChzZWxmKToKCQlkZWYgZG9fZm4oKToKCQkJZXhpdCgyKQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBleDIoc2VsZik6CgkJZGVmIGRvX2ZuKCk6CgkJCW5vbl9leGlzdGVudF9mbigpICAjIG5vcWEKCgkJZ2wuZXFfcHJpbmNpcGxlLnN0cmljdF9lcShkb19mbikKBQ== diff --git a/tests/cases/stable/nondet/leader_errors/simple_valid_err_err.0_0.hash b/tests/cases/stable/nondet/leader_errors/simple_valid_err_err.0_0.hash new file mode 100644 index 000000000..131eae252 --- /dev/null +++ b/tests/cases/stable/nondet/leader_errors/simple_valid_err_err.0_0.hash @@ -0,0 +1 @@ +LRFcZXhpdF9jb2RlIDEABQU= diff --git a/tests/cases/stable/nondet/leader_errors/simple_valid_err_exit.0.hash b/tests/cases/stable/nondet/leader_errors/simple_valid_err_exit.0.hash new file mode 100644 index 000000000..5e5759390 --- /dev/null +++ b/tests/cases/stable/nondet/leader_errors/simple_valid_err_exit.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyIcAgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgZm9vKHNlbGYpOgoJCWRlZiBkb19mbigpOgoJCQlyYWlzZSBFeGNlcHRpb24oKQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBiYXIoc2VsZik6CgkJZGVmIGRvX2ZuKCk6CgkJCXJldHVybgoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBleChzZWxmKToKCQlkZWYgZG9fZm4oKToKCQkJZXhpdCgyKQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBleDIoc2VsZik6CgkJZGVmIGRvX2ZuKCk6CgkJCW5vbl9leGlzdGVudF9mbigpICAjIG5vcWEKCgkJZ2wuZXFfcHJpbmNpcGxlLnN0cmljdF9lcShkb19mbikKBQ== diff --git a/tests/cases/stable/nondet/leader_errors/simple_valid_err_exit.0_0.hash b/tests/cases/stable/nondet/leader_errors/simple_valid_err_exit.0_0.hash new file mode 100644 index 000000000..4467e51b3 --- /dev/null +++ b/tests/cases/stable/nondet/leader_errors/simple_valid_err_exit.0_0.hash @@ -0,0 +1 @@ +LRFcZXhpdF9jb2RlIDIABQU= diff --git a/tests/cases/stable/nondet/leader_errors/simple_valid_err_exit_wrong_err.0.hash b/tests/cases/stable/nondet/leader_errors/simple_valid_err_exit_wrong_err.0.hash new file mode 100644 index 000000000..5e5759390 --- /dev/null +++ b/tests/cases/stable/nondet/leader_errors/simple_valid_err_exit_wrong_err.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyIcAgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgZm9vKHNlbGYpOgoJCWRlZiBkb19mbigpOgoJCQlyYWlzZSBFeGNlcHRpb24oKQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBiYXIoc2VsZik6CgkJZGVmIGRvX2ZuKCk6CgkJCXJldHVybgoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBleChzZWxmKToKCQlkZWYgZG9fZm4oKToKCQkJZXhpdCgyKQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBleDIoc2VsZik6CgkJZGVmIGRvX2ZuKCk6CgkJCW5vbl9leGlzdGVudF9mbigpICAjIG5vcWEKCgkJZ2wuZXFfcHJpbmNpcGxlLnN0cmljdF9lcShkb19mbikKBQ== diff --git a/tests/cases/stable/nondet/leader_errors/simple_valid_err_exit_wrong_err.0_0.hash b/tests/cases/stable/nondet/leader_errors/simple_valid_err_exit_wrong_err.0_0.hash new file mode 100644 index 000000000..defc9c59c --- /dev/null +++ b/tests/cases/stable/nondet/leader_errors/simple_valid_err_exit_wrong_err.0_0.hash @@ -0,0 +1 @@ +LQlcZXhpdF9jb2RlIDEABQU= diff --git a/tests/cases/stable/nondet/leader_errors/simple_valid_err_nerr.0.hash b/tests/cases/stable/nondet/leader_errors/simple_valid_err_nerr.0.hash new file mode 100644 index 000000000..5e5759390 --- /dev/null +++ b/tests/cases/stable/nondet/leader_errors/simple_valid_err_nerr.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyIcAgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgZm9vKHNlbGYpOgoJCWRlZiBkb19mbigpOgoJCQlyYWlzZSBFeGNlcHRpb24oKQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBiYXIoc2VsZik6CgkJZGVmIGRvX2ZuKCk6CgkJCXJldHVybgoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBleChzZWxmKToKCQlkZWYgZG9fZm4oKToKCQkJZXhpdCgyKQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGRvX2ZuKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBleDIoc2VsZik6CgkJZGVmIGRvX2ZuKCk6CgkJCW5vbl9leGlzdGVudF9mbigpICAjIG5vcWEKCgkJZ2wuZXFfcHJpbmNpcGxlLnN0cmljdF9lcShkb19mbikKBQ== diff --git a/tests/cases/stable/nondet/leader_errors/simple_valid_err_nerr.0_0.hash b/tests/cases/stable/nondet/leader_errors/simple_valid_err_nerr.0_0.hash new file mode 100644 index 000000000..131eae252 --- /dev/null +++ b/tests/cases/stable/nondet/leader_errors/simple_valid_err_nerr.0_0.hash @@ -0,0 +1 @@ +LRFcZXhpdF9jb2RlIDEABQU= diff --git a/tests/cases/stable/nondet/metod_det_get_webpage.0.hash b/tests/cases/stable/nondet/metod_det_get_webpage.0.hash new file mode 100644 index 000000000..5a3f58162 --- /dev/null +++ b/tests/cases/stable/nondet/metod_det_get_webpage.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyh8AgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcHJpbnQoJ2luaXQnKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBwdWIoc2VsZik6CgkJZXZhbCgicHJpbnQoJ2luaXQgZnJvbSBwdWIhJykiKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiByYmFjayhzZWxmKToKCQlnbC52bS5Vc2VyRXJyb3IuaW1tZWRpYXRlKCJuYWgsIEkgd29uJ3QgZXhlY3V0ZSIpCgoJZGVmIHByaXYoc2VsZik6CgkJZXZhbCgicHJpbnQoJ2luaXQgZnJvbSBwcml2IScpIikKCglAZ2wucHVibGljLndyaXRlCglkZWYgcmV0bihzZWxmKToKCQlyZXR1cm4geyd4JzogMTB9CgoJQGdsLnB1YmxpYy52aWV3CglkZWYgcmV0bl92aWV3KHNlbGYpOgoJCXJldHVybiB7J3gnOiAxMH0KCglAZ2wucHVibGljLndyaXRlCglkZWYgZGV0X3Zpb2woc2VsZik6CgkJZ2wubm9uZGV0LndlYi5yZW5kZXIoCgkJCSdodHRwczovL3Rlc3Qtc2VydmVyLmdlbmxheWVyLmNvbS9zdGF0aWMvZ2Vudm0vaGVsbG8uaHRtbCcsCgkJCW1vZGU9J3RleHQnLAoJCSkKBQ== diff --git a/tests/cases/stable/nondet/metod_det_get_webpage.0_0.hash b/tests/cases/stable/nondet/metod_det_get_webpage.0_0.hash new file mode 100644 index 000000000..131eae252 --- /dev/null +++ b/tests/cases/stable/nondet/metod_det_get_webpage.0_0.hash @@ -0,0 +1 @@ +LRFcZXhpdF9jb2RlIDEABQU= diff --git a/tests/cases/stable/nondet/trivial.0.hash b/tests/cases/stable/nondet/trivial.0.hash new file mode 100644 index 000000000..4cce027e5 --- /dev/null +++ b/tests/cases/stable/nondet/trivial.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxQqAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgaW5pdChzZWxmKToKCQlldmFsKCJwcmludCgnaW5pdCBmcm9tIGV2YWwhJykiKQoKCQlkZWYgcnVuKCk6CgkJCXByaW50KCd3b3csIG5vbmRldCcpCgkJCXJldHVybiAnd2ViIHBhZ2U/JwoKCQlyZXR1cm4gZ2wuZXFfcHJpbmNpcGxlLnN0cmljdF9lcShydW4pCgAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/nondet/trivial.0_0.hash b/tests/cases/stable/nondet/trivial.0_0.hash new file mode 100644 index 000000000..7ee50db85 --- /dev/null +++ b/tests/cases/stable/nondet/trivial.0_0.hash @@ -0,0 +1 @@ +LQFMd2ViIHBhZ2U/AAUF diff --git a/tests/cases/stable/nondet/validator/rollback_agree.0.hash b/tests/cases/stable/nondet/validator/rollback_agree.0.hash new file mode 100644 index 000000000..8854e7071 --- /dev/null +++ b/tests/cases/stable/nondet/validator/rollback_agree.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxL9AAAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmKToKCQlkZWYgcnVuKCk6CgkJCXJhaXNlIGdsLnZtLlVzZXJFcnJvcigncm9sbGJhY2snKQoKCQlwcmludChnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKHJ1bikpCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/nondet/validator/rollback_agree.0_0.hash b/tests/cases/stable/nondet/validator/rollback_agree.0_0.hash new file mode 100644 index 000000000..42274ec6c --- /dev/null +++ b/tests/cases/stable/nondet/validator/rollback_agree.0_0.hash @@ -0,0 +1 @@ +LQlEcm9sbGJhY2sABQU= diff --git a/tests/cases/stable/nondet/validator/rollback_disagree.0.hash b/tests/cases/stable/nondet/validator/rollback_disagree.0.hash new file mode 100644 index 000000000..8854e7071 --- /dev/null +++ b/tests/cases/stable/nondet/validator/rollback_disagree.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxL9AAAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmKToKCQlkZWYgcnVuKCk6CgkJCXJhaXNlIGdsLnZtLlVzZXJFcnJvcigncm9sbGJhY2snKQoKCQlwcmludChnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKHJ1bikpCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/nondet/validator/rollback_disagree.0_0.hash b/tests/cases/stable/nondet/validator/rollback_disagree.0_0.hash new file mode 100644 index 000000000..c677e6b07 --- /dev/null +++ b/tests/cases/stable/nondet/validator/rollback_disagree.0_0.hash @@ -0,0 +1 @@ +LQl0b3RoZXIgcm9sbGJhY2sABQU= diff --git a/tests/cases/stable/nondet/validator/rollback_imm.0.hash b/tests/cases/stable/nondet/validator/rollback_imm.0.hash new file mode 100644 index 000000000..ea42dfb39 --- /dev/null +++ b/tests/cases/stable/nondet/validator/rollback_imm.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxIBAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmKToKCQlkZWYgcnVuKCk6CgkJCWdsLnZtLlVzZXJFcnJvci5pbW1lZGlhdGUoJ3JvbGxiYWNrJykKCgkJcHJpbnQoZ2wuZXFfcHJpbmNpcGxlLnN0cmljdF9lcShydW4pKQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/nondet/validator/rollback_imm.0_0.hash b/tests/cases/stable/nondet/validator/rollback_imm.0_0.hash new file mode 100644 index 000000000..42274ec6c --- /dev/null +++ b/tests/cases/stable/nondet/validator/rollback_imm.0_0.hash @@ -0,0 +1 @@ +LQlEcm9sbGJhY2sABQU= diff --git a/tests/cases/stable/nondet/validator/rollback_imm.0_1.hash b/tests/cases/stable/nondet/validator/rollback_imm.0_1.hash new file mode 100644 index 000000000..c677e6b07 --- /dev/null +++ b/tests/cases/stable/nondet/validator/rollback_imm.0_1.hash @@ -0,0 +1 @@ +LQl0b3RoZXIgcm9sbGJhY2sABQU= diff --git a/tests/cases/stable/nondet/validator/rollback_imm.0_2.hash b/tests/cases/stable/nondet/validator/rollback_imm.0_2.hash new file mode 100644 index 000000000..def506bc7 --- /dev/null +++ b/tests/cases/stable/nondet/validator/rollback_imm.0_2.hash @@ -0,0 +1 @@ +LQkJAAUF diff --git a/tests/cases/stable/nondet/validator/sync.0.hash b/tests/cases/stable/nondet/validator/sync.0.hash new file mode 100644 index 000000000..b1a3028bf --- /dev/null +++ b/tests/cases/stable/nondet/validator/sync.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxIHAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmKToKCQlkZWYgcnVuKCk6CgkJCXByaW50KCdTSE9VTEQgTk9UIEJFIFBSSU5URUQnKQoJCQlyZXR1cm4gMTAKCgkJcHJpbnQoZ2wuZXFfcHJpbmNpcGxlLnN0cmljdF9lcShydW4pKQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/nondet/validator/sync.0_0.hash b/tests/cases/stable/nondet/validator/sync.0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/nondet/validator/sync.0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/nondet/validator/sync_err.0.hash b/tests/cases/stable/nondet/validator/sync_err.0.hash new file mode 100644 index 000000000..b1a3028bf --- /dev/null +++ b/tests/cases/stable/nondet/validator/sync_err.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxIHAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmKToKCQlkZWYgcnVuKCk6CgkJCXByaW50KCdTSE9VTEQgTk9UIEJFIFBSSU5URUQnKQoJCQlyZXR1cm4gMTAKCgkJcHJpbnQoZ2wuZXFfcHJpbmNpcGxlLnN0cmljdF9lcShydW4pKQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/nondet/validator/sync_err.0_0.hash b/tests/cases/stable/nondet/validator/sync_err.0_0.hash new file mode 100644 index 000000000..14442bec8 --- /dev/null +++ b/tests/cases/stable/nondet/validator/sync_err.0_0.hash @@ -0,0 +1 @@ +LQk8Tm8gaWRlYQAFBQ== diff --git a/tests/cases/stable/py/balances/balance.0.hash b/tests/cases/stable/py/balances/balance.0.hash new file mode 100644 index 000000000..b4d1ed009 --- /dev/null +++ b/tests/cases/stable/py/balances/balance.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgzINAwAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcGFzcwoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYpOgoJCXByaW50KCdtYWluIHNlbGYnLCBzZWxmLmJhbGFuY2UpCgkJcHJpbnQoJ21haW4gQXQoc2VsZiknLCBnbC5jb250cmFjdC5nZXRfYXQoZ2wubWVzc2FnZS5jb250cmFjdF9hZGRyZXNzKS5iYWxhbmNlKQoJCXByaW50KCc9PT0gdHJhbnNmZXIgPT09JykKCQlnbC5jb250cmFjdC5nZXRfYXQoZ2wubWVzc2FnZS5zZW5kZXJfYWRkcmVzcykuZW1pdF90cmFuc2Zlcih2YWx1ZT01KQoJCXByaW50KCdtYWluIHNlbGYnLCBzZWxmLmJhbGFuY2UpCgkJcHJpbnQoJ21haW4gQXQoc2VsZiknLCBnbC5jb250cmFjdC5nZXRfYXQoZ2wubWVzc2FnZS5jb250cmFjdF9hZGRyZXNzKS5iYWxhbmNlKQoKCQlwcmludCgnPT09IGNhbGwgLnZpZXcoKSA9PT0nKQoJCWdsLmNvbnRyYWN0LmdldF9hdChnbC5tZXNzYWdlLmNvbnRyYWN0X2FkZHJlc3MpLnZpZXcoKS5uZXN0ZWQoKQoKCUBnbC5wdWJsaWMudmlldwoJZGVmIG5lc3RlZChzZWxmKToKCQlwcmludCgnbmVzdGVkIHNlbGYnLCBzZWxmLmJhbGFuY2UpCgkJcHJpbnQoJ25lc3RlZCBBdChzZWxmKScsIGdsLmNvbnRyYWN0LmdldF9hdChnbC5tZXNzYWdlLmNvbnRyYWN0X2FkZHJlc3MpLmJhbGFuY2UpCgAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/balances/balance.0_0.hash b/tests/cases/stable/py/balances/balance.0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/balances/balance.0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/balances/balance_eth.0.hash b/tests/cases/stable/py/balances/balance_eth.0.hash new file mode 100644 index 000000000..93b7a6d56 --- /dev/null +++ b/tests/cases/stable/py/balances/balance_eth.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgzZMAwAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpAZ2wuZXZtLmNvbnRyYWN0X2ludGVyZmFjZQpjbGFzcyBFdGhDb250cmFjdDoKCWNsYXNzIFZpZXc6CgkJcGFzcwoKCWNsYXNzIFdyaXRlOgoJCXBhc3MKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcGFzcwoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYpOgoJCXByaW50KCdtYWluIHNlbGYnLCBzZWxmLmJhbGFuY2UpCgkJcHJpbnQoJ21haW4gQXQoc2VsZiknLCBFdGhDb250cmFjdChnbC5tZXNzYWdlLmNvbnRyYWN0X2FkZHJlc3MpLmJhbGFuY2UpCgkJcHJpbnQoJz09PSB0cmFuc2ZlciA9PT0nKQoKCQlFdGhDb250cmFjdChnbC5tZXNzYWdlLnNlbmRlcl9hZGRyZXNzKS5lbWl0X3RyYW5zZmVyKHZhbHVlPTUpCgkJcHJpbnQoJ21haW4gc2VsZicsIHNlbGYuYmFsYW5jZSkKCQlwcmludCgnbWFpbiBBdChzZWxmKScsIEV0aENvbnRyYWN0KGdsLm1lc3NhZ2UuY29udHJhY3RfYWRkcmVzcykuYmFsYW5jZSkKCgkJcHJpbnQoJz09PSBjYWxsIC52aWV3KCkgPT09JykKCQlnbC5jb250cmFjdC5nZXRfYXQoZ2wubWVzc2FnZS5jb250cmFjdF9hZGRyZXNzKS52aWV3KCkubmVzdGVkKCkKCglAZ2wucHVibGljLnZpZXcKCWRlZiBuZXN0ZWQoc2VsZik6CgkJcHJpbnQoJ25lc3RlZCBzZWxmJywgc2VsZi5iYWxhbmNlKQoJCXByaW50KCduZXN0ZWQgQXQoc2VsZiknLCBFdGhDb250cmFjdChnbC5tZXNzYWdlLmNvbnRyYWN0X2FkZHJlc3MpLmJhbGFuY2UpCgAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/py/balances/balance_eth.0_0.hash b/tests/cases/stable/py/balances/balance_eth.0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/balances/balance_eth.0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/balances/sandbox_overspend.0.hash b/tests/cases/stable/py/balances/sandbox_overspend.0.hash new file mode 100644 index 000000000..0f28b0285 --- /dev/null +++ b/tests/cases/stable/py/balances/sandbox_overspend.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAg0ZGBAAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJZGVmIF9faW5pdF9fKHNlbGYpOgoJCWJhbGFuY2VfYmVmb3JlID0gc2VsZi5iYWxhbmNlCgkJdGFyZ2V0ID0gZ2wubWVzc2FnZS5zZW5kZXJfYWRkcmVzcwoKCQkjIEZpcnN0IHRyYW5zZmVyOiBzcGVuZCA2MCBvdXQgb2YgMTAwCgkJZ2wuY29udHJhY3QuZ2V0X2F0KHRhcmdldCkuZW1pdF90cmFuc2Zlcih2YWx1ZT02MCkKCQliYWxhbmNlX2FmdGVyX2ZpcnN0ID0gc2VsZi5iYWxhbmNlCgkJcHJpbnQoZidiYWxhbmNlIGJlZm9yZT17YmFsYW5jZV9iZWZvcmV9IGFmdGVyX2ZpcnN0X3NlbmQ9e2JhbGFuY2VfYWZ0ZXJfZmlyc3R9JykKCgkJIyBOb3cgc3Bhd24gYSBzYW5kYm94IHdpdGggbWVzc2FnZSBzZW5kaW5nIGFsbG93ZWQuCgkJIyBCVUc6IHRoZSBzYW5kYm94IGdldHMgYSBmcmVzaCBtZXNzYWdlc19kZWNyZW1lbnRlZD0wLAoJCSMgc28gaXQgdGhpbmtzIHRoZSBmdWxsIGJhbGFuY2UgaXMgc3RpbGwgYXZhaWxhYmxlLgoJCWRlZiBzYW5kYm94X2ZuKCk6CgkJCSMgU2Vjb25kIHRyYW5zZmVyOiBzcGVuZCBhbm90aGVyIDYwIGluc2lkZSBzYW5kYm94CgkJCSMgVGhpcyBzaG91bGQgZmFpbCAodG90YWwgMTIwID4gMTAwKSBidXQgdGhlIHNhbmRib3gKCQkJIyBkb2Vzbid0IGtub3cgYWJvdXQgdGhlIHBhcmVudCdzIDYwIGFscmVhZHkgc3BlbnQuCgkJCWdsLmNvbnRyYWN0LmdldF9hdCh0YXJnZXQpLmVtaXRfdHJhbnNmZXIodmFsdWU9NjApCgkJCXJldHVybiBzZWxmLmJhbGFuY2UKCgkJcmVzdWx0ID0gZ2wudm0uc3Bhd25fc2FuZGJveChzYW5kYm94X2ZuLCBhbGxvd19zZW5kX21lc3NhZ2VzPVRydWUpCgkJcHJpbnQoZidzYW5kYm94IHJlc3VsdD17cmVzdWx0fScpCgkJcHJpbnQoZidiYWxhbmNlIGZpbmFsPXtzZWxmLmJhbGFuY2V9JykKCQkjIElmIHdlIHJlYWNoIGhlcmUgd2l0aCBib3RoIHRyYW5zZmVycyBhY2NlcHRlZCwKCQkjIHRvdGFsIHNwZW50IGlzIDEyMCBidXQgYmFsYW5jZSB3YXMgb25seSAxMDAgPT4gb3ZlcnNwZW5kIGJ1ZwoAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/balances/sandbox_overspend_2.0.hash b/tests/cases/stable/py/balances/sandbox_overspend_2.0.hash new file mode 100644 index 000000000..2e5e6c0c0 --- /dev/null +++ b/tests/cases/stable/py/balances/sandbox_overspend_2.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyhmAgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJZGVmIF9faW5pdF9fKHNlbGYpOgoJCXRhcmdldCA9IGdsLm1lc3NhZ2Uuc2VuZGVyX2FkZHJlc3MKCgkJcHJpbnQoZidiYWxhbmNlIGJlZm9yZT17c2VsZi5iYWxhbmNlfScpCgoJCWRlZiBzYW5kYm94X2ZuKCk6CgkJCWdsLmNvbnRyYWN0LmdldF9hdCh0YXJnZXQpLmVtaXRfdHJhbnNmZXIodmFsdWU9NjApCgkJCXJldHVybiBzZWxmLmJhbGFuY2UKCgkJcmVzdWx0ID0gZ2wudm0uc3Bhd25fc2FuZGJveChzYW5kYm94X2ZuLCBhbGxvd19zZW5kX21lc3NhZ2VzPVRydWUpCgkJcHJpbnQoZidzYW5kYm94IHJlc3VsdD17cmVzdWx0fSBiYWxhbmNlIGFmdGVyIHNhbmRib3g9e3NlbGYuYmFsYW5jZX0nKQoKCQl0cnk6CgkJCWdsLmNvbnRyYWN0LmdldF9hdCh0YXJnZXQpLmVtaXRfdHJhbnNmZXIodmFsdWU9NjApCgkJZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgoJCQlwcmludChmJ3RyYW5zZmVyIGZhaWxlZCB3aXRoIGVycm9yOiB7ZX0nKQoKCQlwcmludChmJ2JhbGFuY2UgZmluYWw9e3NlbGYuYmFsYW5jZX0nKQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/balances/undefined_all.0.hash b/tests/cases/stable/py/balances/undefined_all.0.hash new file mode 100644 index 000000000..3bb985429 --- /dev/null +++ b/tests/cases/stable/py/balances/undefined_all.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgwqGAAAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJcGFzcwoAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/balances/undefined_all.0_0.hash b/tests/cases/stable/py/balances/undefined_all.0_0.hash new file mode 100644 index 000000000..131eae252 --- /dev/null +++ b/tests/cases/stable/py/balances/undefined_all.0_0.hash @@ -0,0 +1 @@ +LRFcZXhpdF9jb2RlIDEABQU= diff --git a/tests/cases/stable/py/balances/undefined_all.0_0_0.hash b/tests/cases/stable/py/balances/undefined_all.0_0_0.hash new file mode 100644 index 000000000..131eae252 --- /dev/null +++ b/tests/cases/stable/py/balances/undefined_all.0_0_0.hash @@ -0,0 +1 @@ +LRFcZXhpdF9jb2RlIDEABQU= diff --git a/tests/cases/stable/py/balances/undefined_method.0.hash b/tests/cases/stable/py/balances/undefined_method.0.hash new file mode 100644 index 000000000..75017cc70 --- /dev/null +++ b/tests/cases/stable/py/balances/undefined_method.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyQrAgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCgppbXBvcnQgdHlwaW5nCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIF9faGFuZGxlX3VuZGVmaW5lZF9tZXRob2RfXygKCQlzZWxmLCBtZXRob2RfbmFtZTogc3RyLCBhcmdzOiBsaXN0W3R5cGluZy5BbnldLCBrd2FyZ3M6IGRpY3Rbc3RyLCB0eXBpbmcuQW55XQoJKToKCQlwcmludCgKCQkJewoJCQkJJ21lJzogJ19faGFuZGxlX3VuZGVmaW5lZF9tZXRob2RfXycsCgkJCQknbWV0aG9kX25hbWUnOiBtZXRob2RfbmFtZSwKCQkJCSdhcmdzJzogYXJncywKCQkJCSdrd2FyZ3MnOiBrd2FyZ3MsCgkJCQkndmFsdWUnOiBnbC5tZXNzYWdlLnZhbHVlLAoJCQl9CgkJKQoKCUBnbC5wdWJsaWMud3JpdGUucGF5YWJsZQoJZGVmIF9fcmVjZWl2ZV9fKHNlbGYpOgoJCXByaW50KHsnbWUnOiAnX19yZWNlaXZlX18nLCAndmFsdWUnOiBnbC5tZXNzYWdlLnZhbHVlfSkKAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/py/balances/undefined_method.0_0.hash b/tests/cases/stable/py/balances/undefined_method.0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/balances/undefined_method.0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/balances/undefined_method.0_0_0.hash b/tests/cases/stable/py/balances/undefined_method.0_0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/balances/undefined_method.0_0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/balances/undefined_method_payable.0.hash b/tests/cases/stable/py/balances/undefined_method_payable.0.hash new file mode 100644 index 000000000..3b359332c --- /dev/null +++ b/tests/cases/stable/py/balances/undefined_method_payable.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyQzAgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCgppbXBvcnQgdHlwaW5nCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJQGdsLnB1YmxpYy53cml0ZS5wYXlhYmxlCglkZWYgX19oYW5kbGVfdW5kZWZpbmVkX21ldGhvZF9fKAoJCXNlbGYsIG1ldGhvZF9uYW1lOiBzdHIsIGFyZ3M6IGxpc3RbdHlwaW5nLkFueV0sIGt3YXJnczogZGljdFtzdHIsIHR5cGluZy5BbnldCgkpOgoJCXByaW50KAoJCQl7CgkJCQknbWUnOiAnX19oYW5kbGVfdW5kZWZpbmVkX21ldGhvZF9fJywKCQkJCSdtZXRob2RfbmFtZSc6IG1ldGhvZF9uYW1lLAoJCQkJJ2FyZ3MnOiBhcmdzLAoJCQkJJ2t3YXJncyc6IGt3YXJncywKCQkJCSd2YWx1ZSc6IGdsLm1lc3NhZ2UudmFsdWUsCgkJCX0KCQkpCgoJQGdsLnB1YmxpYy53cml0ZS5wYXlhYmxlCglkZWYgX19yZWNlaXZlX18oc2VsZik6CgkJcHJpbnQoeydtZSc6ICdfX3JlY2VpdmVfXycsICd2YWx1ZSc6IGdsLm1lc3NhZ2UudmFsdWV9KQoAAAAAAAAAAAAF diff --git a/tests/cases/stable/py/balances/undefined_method_payable.0_0.hash b/tests/cases/stable/py/balances/undefined_method_payable.0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/balances/undefined_method_payable.0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/balances/undefined_method_payable.0_0_0.hash b/tests/cases/stable/py/balances/undefined_method_payable.0_0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/balances/undefined_method_payable.0_0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/balances/undefined_receive.0.hash b/tests/cases/stable/py/balances/undefined_receive.0.hash new file mode 100644 index 000000000..bbbc02089 --- /dev/null +++ b/tests/cases/stable/py/balances/undefined_receive.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgx7GAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCgppbXBvcnQgdHlwaW5nCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJQGdsLnB1YmxpYy53cml0ZS5wYXlhYmxlCglkZWYgX19oYW5kbGVfdW5kZWZpbmVkX21ldGhvZF9fKAoJCXNlbGYsIG1ldGhvZF9uYW1lOiBzdHIsIGFyZ3M6IGxpc3RbdHlwaW5nLkFueV0sIGt3YXJnczogZGljdFtzdHIsIHR5cGluZy5BbnldCgkpOgoJCXByaW50KAoJCQl7CgkJCQknbWUnOiAnX19oYW5kbGVfdW5kZWZpbmVkX21ldGhvZF9fJywKCQkJCSdtZXRob2RfbmFtZSc6IG1ldGhvZF9uYW1lLAoJCQkJJ2FyZ3MnOiBhcmdzLAoJCQkJJ2t3YXJncyc6IGt3YXJncywKCQkJCSd2YWx1ZSc6IGdsLm1lc3NhZ2UudmFsdWUsCgkJCX0KCQkpCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/py/balances/undefined_receive.0_0.hash b/tests/cases/stable/py/balances/undefined_receive.0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/balances/undefined_receive.0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/balances/undefined_receive.0_0_0.hash b/tests/cases/stable/py/balances/undefined_receive.0_0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/balances/undefined_receive.0_0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/embeddings/simple.0.hash b/tests/cases/stable/py/embeddings/simple.0.hash new file mode 100644 index 000000000..5a30c2aa2 --- /dev/null +++ b/tests/cases/stable/py/embeddings/simple.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyIQAgAAIyB7CiMgICAiU2VxIjogWwojICAgICB7ICJEZXBlbmRzIjogInB5LWxpYi1nZW5sYXllci1lbWJlZGRpbmdzOnRlc3QiIH0sCiMgICAgIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQojICAgXQojIH0KCmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCmltcG9ydCBnZW5sYXllcl9lbWJlZGRpbmdzIGFzIGdsZQoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYsIGRldDogYm9vbCk6CgkJZGVmIG5kX2Jsb2NrKCk6CgkJCWVtYmVkZGluZ3NfZ2VuZXJhdG9yID0gZ2xlLlNlbnRlbmNlVHJhbnNmb3JtZXIoJ2FsbC1NaW5pTE0tTDYtdjInKQoJCQlyZWFsID0gZW1iZWRkaW5nc19nZW5lcmF0b3IoJ3doYXQgaXMgZ2VubGF5ZXI/JykKCQkJcHJpbnQocmVhbC5zdW0oKSkKCgkJaWYgZGV0OgoJCQluZF9ibG9jaygpCgkJZWxzZToKCQkJZ2wuZXFfcHJpbmNpcGxlLnN0cmljdF9lcShuZF9ibG9jaykKAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/embeddings/simple.0_0.hash b/tests/cases/stable/py/embeddings/simple.0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/embeddings/simple.0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/embeddings/simple_det.0.hash b/tests/cases/stable/py/embeddings/simple_det.0.hash new file mode 100644 index 000000000..5a30c2aa2 --- /dev/null +++ b/tests/cases/stable/py/embeddings/simple_det.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyIQAgAAIyB7CiMgICAiU2VxIjogWwojICAgICB7ICJEZXBlbmRzIjogInB5LWxpYi1nZW5sYXllci1lbWJlZGRpbmdzOnRlc3QiIH0sCiMgICAgIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQojICAgXQojIH0KCmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCmltcG9ydCBnZW5sYXllcl9lbWJlZGRpbmdzIGFzIGdsZQoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYsIGRldDogYm9vbCk6CgkJZGVmIG5kX2Jsb2NrKCk6CgkJCWVtYmVkZGluZ3NfZ2VuZXJhdG9yID0gZ2xlLlNlbnRlbmNlVHJhbnNmb3JtZXIoJ2FsbC1NaW5pTE0tTDYtdjInKQoJCQlyZWFsID0gZW1iZWRkaW5nc19nZW5lcmF0b3IoJ3doYXQgaXMgZ2VubGF5ZXI/JykKCQkJcHJpbnQocmVhbC5zdW0oKSkKCgkJaWYgZGV0OgoJCQluZF9ibG9jaygpCgkJZWxzZToKCQkJZ2wuZXFfcHJpbmNpcGxlLnN0cmljdF9lcShuZF9ibG9jaykKAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/embeddings/simple_det.0_0.hash b/tests/cases/stable/py/embeddings/simple_det.0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/embeddings/simple_det.0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/embeddings/simple_tokenizer.0.hash b/tests/cases/stable/py/embeddings/simple_tokenizer.0.hash new file mode 100644 index 000000000..b5e0443c9 --- /dev/null +++ b/tests/cases/stable/py/embeddings/simple_tokenizer.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgx7AAQAAIyB7CiMgICAiU2VxIjogWwojICAgICB7ICJEZXBlbmRzIjogInB5LWxpYi13b3JkX3BpZWNlX3Rva2VuaXplcjp0ZXN0IiB9LAojICAgICB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KIyAgIF0KIyB9CgppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgppbXBvcnQgd29yZF9waWVjZV90b2tlbml6ZXIKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmLCBkZXQ6IGJvb2wpOgoJCXRva2VuaXplciA9IHdvcmRfcGllY2VfdG9rZW5pemVyLldvcmRQaWVjZVRva2VuaXplcigpCgoJCWZvciB0eHQgaW4gWycjIycsICcjaGFzaHRhZycsICdlbW9qaSDwn5qA8J+agPCfmoAnXToKCQkJcHJpbnQoZid7dHh0fToge3Rva2VuaXplci50b2tlbml6ZSh0eHQpfScpCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/py/embeddings/simple_tokenizer.0_0.hash b/tests/cases/stable/py/embeddings/simple_tokenizer.0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/embeddings/simple_tokenizer.0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/embeddings/vecdb.0.hash b/tests/cases/stable/py/embeddings/vecdb.0.hash new file mode 100644 index 000000000..605dae57a --- /dev/null +++ b/tests/cases/stable/py/embeddings/vecdb.0.hash @@ -0,0 +1 @@ +LQEAAE0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCRguJG4z2Zcn50QmRH3rALC+mIPXPtdaG+blrLD/wTyQAAAAAgwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAkarTtJntGExRjClCClTeapPszpBSCLunXLw6y4spm7AAAAAAIMCAACAPwAAAEAAAEBAAACAQAAAoEAAAAAAAAAAAAAAAAAVowKADV6GQrOtRCKTv5ViYIZpoqvlnFVGfEwBMkHDV50C2gAAAACDAgMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCqm3G4qVvBmYbgUYDTC0yiG8/FEaDXEQFZ3n0cCg1s7cAAAAAgwIAAAAAAAAAAAAAAAD/////AAAAAAAAAAAAAAAAAAAAABWjAq744hjkeWut5b9uW2fTvO39XzVEOvLEnDYFB22lgxghAAAAAIMCMTIzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDIPkBAAAjIHsKIyAgICJTZXEiOiBbCiMgICAgIHsgIkRlcGVuZHMiOiAicHktbGliLWdlbmxheWVyLWVtYmVkZGluZ3M6dGVzdCIgfSwKIyAgICAgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CiMgICBdCiMgfQoKCmltcG9ydCBudW1weSBhcyBucAppbXBvcnQgdHlwaW5nCmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCmltcG9ydCBnZW5sYXllcl9lbWJlZGRpbmdzIGFzIGdsZQoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCXg6IGdsZS5WZWNEQltucC5mbG9hdDMyLCB0eXBpbmcuTGl0ZXJhbFs1XSwgc3RyLCBnbGUuRXVjbGlkZWFuRGlzdGFuY2VdCgoJZGVmIF9faW5pdF9fKHNlbGYpOgoJCXNlbGYueC5pbnNlcnQobnAuYXJyYXkoWzEsIDIsIDMsIDQsIDVdLCBkdHlwZT1ucC5mbG9hdDMyKSwgJzEyMycpCgkJcHJpbnQobGlzdChzZWxmLngua25uKG5wLm9uZXMoNSwgZHR5cGU9bnAuZmxvYXQzMiksIDEpKSkKAAAAFaMC4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhecAAAAAgwYBAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAAAAAAAAAAAzczMzMzM9D8AAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/py/events/post_event.0.hash b/tests/cases/stable/py/events/post_event.0.hash new file mode 100644 index 000000000..428d18171 --- /dev/null +++ b/tests/cases/stable/py/events/post_event.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyZQAgAAIyB2MC4xLjUKIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBUZXN0RXZlbnQoZ2wuY2hhaW4uRXZlbnQpOgoJZGVmIF9faW5pdF9fKHNlbGYsIHVzZXJfaWQ6IGludCwgYWN0aW9uOiBzdHIsIC8sICoqYmxvYik6IC4uLgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQl0cnk6CgkJCSMgVGVzdCBiYXNpYyBldmVudCBlbWlzc2lvbgoJCQlUZXN0RXZlbnQoNDIsICdjcmVhdGUnLCB0aW1lc3RhbXA9MTIzNDU2Nzg5MCwgZGF0YT0ndGVzdF9kYXRhJykuZW1pdCgpCgoJCQkjIFRlc3QgZXZlbnQgd2l0aCBkaWZmZXJlbnQgcGFyYW1ldGVycwoJCQlUZXN0RXZlbnQoMTAwLCAndXBkYXRlJywgYW1vdW50PTUwMCwgZGVzY3JpcHRpb249J1VwZGF0ZWQgcmVjb3JkJykuZW1pdCgpCgoJCQlwcmludCgnRXZlbnRzIGVtaXR0ZWQgc3VjY2Vzc2Z1bGx5JykKCQlleGNlcHQgRXhjZXB0aW9uIGFzIGU6CgkJCXByaW50KGYnRXJyb3IgZW1pdHRpbmcgZXZlbnQ6IHtlfScpCgAAAAAAAAAAAAAAABUlgwK0dR31Zfw1VHZOJ5CUOWDJzf589RAzHbKYgb8VI7QNrIMC0QIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAjRjcmVhdGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuwMmBmFjdGlvbtECBGRhdGFMdGVzdF9kYXRhCXRpbWVzdGFtcJGtwOUkB3VzZXJfaWQ0Y3JlYXRlJYMCtHUd9WX8NVR2TieQlDlgyc3+fPUQMx2ymIG/FSO0DayDAqEGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgwI0dXBkYXRlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOsDJgZhY3Rpb26hBgZhbW91bnShHwtkZXNjcmlwdGlvbnRVcGRhdGVkIHJlY29yZAd1c2VyX2lkNHVwZGF0ZQ== diff --git a/tests/cases/stable/py/intercontract/call_self_view.0.hash b/tests/cases/stable/py/intercontract/call_self_view.0.hash new file mode 100644 index 000000000..55e672fe9 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_self_view.0.hash @@ -0,0 +1 @@ +LRG0AmludmFsaWRfY29udHJhY3QgYWJzZW50X3J1bm5lcl9jb21tZW50AB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyDoAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJIyBzZWxmLUNhbGxDb250cmFjdCBpbnRvIG91ciBvd24gdmlldyBtZXRob2QgZHVyaW5nIGRlcGxveTogb3VyIGNvZGUgaXMKCQkjIG5vdCBjb21taXR0ZWQgb24tY2hhaW4geWV0LCBzbyBpdCBpcyBub3QgdmlzaWJsZSBhcyBhbiBgOmFgIHJ1bm5lciBhbmQKCQkjIHRoaXMgZmFpbHMgd2l0aCBgaW52YWxpZF9jb250cmFjdGAgKGFib3J0aW5nIHRoZSBkZXBsb3kpCgkJcHJpbnQoJ3NlbGYgdmlldyAtPicsIGdsLmNvbnRyYWN0LmdldF9hdChzZWxmLmFkZHJlc3MpLnZpZXcoKS5yZWFkMzAoKSkKCglAZ2wucHVibGljLnZpZXcKCWRlZiByZWFkMzAoc2VsZikgLT4gaW50OgoJCXJldHVybiAzMAoAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/intercontract/call_view.0.hash b/tests/cases/stable/py/intercontract/call_view.0.hash new file mode 100644 index 000000000..59d2c3dc0 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_view.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxIXAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcGFzcwoKCUBnbC5wdWJsaWMudmlldwoJZGVmIGZvbyhzZWxmLCBhLCBiKToKCQlwcmludCgnY29udHJhY3QgdG8uZm9vJykKCQlpbXBvcnQganNvbgoKCQlqc29uLmxvYWRzID0gMTEgICMgZXZpbCEKCQlyZXR1cm4gYSArIGIKAAAAAAAF diff --git a/tests/cases/stable/py/intercontract/call_view.0_0.hash b/tests/cases/stable/py/intercontract/call_view.0_0.hash new file mode 100644 index 000000000..bde386ddf --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_view.0_0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxQfAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcGFzcwoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYsIGFkZHI6IEFkZHJlc3MpOgoJCXByaW50KCdjb250cmFjdCBmcm9tLm1haW4nKQoJCXByaW50KGdsLmNvbnRyYWN0LmdldF9hdChhZGRyKS52aWV3KCkuZm9vKDEsIDIpKQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/intercontract/call_view.0_0_0.hash b/tests/cases/stable/py/intercontract/call_view.0_0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_view.0_0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/intercontract/call_view_committed.0.hash b/tests/cases/stable/py/intercontract/call_view_committed.0.hash new file mode 100644 index 000000000..10bf43021 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_view_committed.0.hash @@ -0,0 +1 @@ +LQEAACUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgzqOAwAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6Cgl4OiB1MzIKCXdyaXRlX2Fuc3dlcjogZ2wuRHluQXJyYXlbdTMyXQoKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlzZWxmLnggPSAxCgoJQGdsLnB1YmxpYy52aWV3CglkZWYgZG9fcmVhZChzZWxmKSAtPiB1MzI6CgkJcmV0dXJuIHNlbGYueAoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBkb190ZXN0KHNlbGYpOgoJCSMgQSBkaXJlY3QgcmVhZCBzZWVzIHRoZSBpbi10cmFuc2FjdGlvbiBkZWx0YTsgYSBDYWxsQ29udHJhY3QgKHZpZXcpIHJlYWRzCgkJIyBjb21taXR0ZWQgb24tY2hhaW4gc3RhdGUgYW5kIGRvZXMgTk9UIHNlZSB0aGUgdW5jb21taXR0ZWQgd3JpdGUgYmVsb3cuCgkJc2VsZi53cml0ZV9hbnN3ZXIuYXBwZW5kKHNlbGYuZG9fcmVhZCgpKSAgIyAxCgkJc2VsZi53cml0ZV9hbnN3ZXIuYXBwZW5kKAoJCQlnbC5jb250cmFjdC5nZXRfYXQoc2VsZi5hZGRyZXNzKS52aWV3KCkuZG9fcmVhZCgpCgkJKSAgIyAxIChjb21taXR0ZWQpCgkJc2VsZi53cml0ZV9hbnN3ZXIuYXBwZW5kKHNlbGYuZG9fcmVhZCgpKSAgIyAxCgoJCXNlbGYueCA9IDMwCgoJCXNlbGYud3JpdGVfYW5zd2VyLmFwcGVuZChzZWxmLmRvX3JlYWQoKSkgICMgMzAgKGRlbHRhKQoJCXNlbGYud3JpdGVfYW5zd2VyLmFwcGVuZCgKCQkJZ2wuY29udHJhY3QuZ2V0X2F0KHNlbGYuYWRkcmVzcykudmlldygpLmRvX3JlYWQoKQoJCSkgICMgMSAoY29tbWl0dGVkKQoJCXNlbGYud3JpdGVfYW5zd2VyLmFwcGVuZChzZWxmLmRvX3JlYWQoKSkgICMgMzAKCgkJcHJpbnQobGlzdChzZWxmLndyaXRlX2Fuc3dlcikpCgAAAAAAAAAAAAAAAAAAFaMC4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhecAAAAAgwIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/intercontract/call_view_committed.0_0.hash b/tests/cases/stable/py/intercontract/call_view_committed.0_0.hash new file mode 100644 index 000000000..1f52e4217 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_view_committed.0_0.hash @@ -0,0 +1 @@ +LQEAABUVowKADV6GQrOtRCKTv5ViYIZpoqvlnFVGfEwBMkHDV50C2gAAAACDAgEAAAABAAAAAQAAAB4AAAABAAAAHgAAAAAAAAAAAAAAFaMC4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhecAAAAAgwIeAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/intercontract/call_view_emit.0.hash b/tests/cases/stable/py/intercontract/call_view_emit.0.hash new file mode 100644 index 000000000..e2e82ea6a --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_view_emit.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyytAgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBQaW5nZWQoZ2wuY2hhaW4uRXZlbnQpOgoJZGVmIF9faW5pdF9fKHNlbGYsIHdobzogc3RyLCAvLCAqKmJsb2IpOiAuLi4KCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcGFzcwoKCUBnbC5wdWJsaWMudmlldwoJZGVmIHBpbmcoc2VsZikgLT4gc3RyOgoJCSMgaW5zaWRlIGEgQ2FsbENvbnRyYWN0IGNoaWxkIFZNIChyZWFkLW9ubHkgLyBzdGF0aWMgY2FsbCkKCQl0cnk6CgkJCVBpbmdlZCgnYicsIG5vdGU9J2VtaXR0ZWQgZHVyaW5nIENhbGxDb250cmFjdCcpLmVtaXQoKQoJCQlwcmludCgnQiBlbWl0OiBvaycpCgkJZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgoJCQlwcmludChmJ0IgZW1pdCBmb3JiaWRkZW46IHt0eXBlKGUpLl9fbmFtZV9ffScpCgkJdHJ5OgoJCQlnbC5jb250cmFjdC5nZXRfYXQoZ2wuQWRkcmVzcyhiJ1x4MzAnICogMjApKS5lbWl0KCkuZm9vKDEsIDIpCgkJCXByaW50KCdCIHNlbmQ6IG9rJykKCQlleGNlcHQgRXhjZXB0aW9uIGFzIGU6CgkJCXByaW50KGYnQiBzZW5kIGZvcmJpZGRlbjoge3R5cGUoZSkuX19uYW1lX199JykKCQlyZXR1cm4gJ3BvbmcnCgAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/intercontract/call_view_emit.0_0.hash b/tests/cases/stable/py/intercontract/call_view_emit.0_0.hash new file mode 100644 index 000000000..d9522f231 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_view_emit.0_0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyDoAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcGFzcwoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYsIGFkZHI6IEFkZHJlc3MpOgoJCSMgcmVhZC1vbmx5IENhbGxDb250cmFjdCBpbnRvIEI7IEIgdHJpZXMgdG8gZW1pdCBhbiBldmVudCBhbmQgc2VuZCBhCgkJIyBtZXNzYWdlIGluc2lkZSBpdC4gQm90aCBtdXN0IGZhaWwgYmVjYXVzZSB0aGUgY2hpbGQgaXMgYSBzdGF0aWMgY2FsbC4KCQl0cnk6CgkJCXByaW50KCdBIGdvdCcsIGdsLmNvbnRyYWN0LmdldF9hdChhZGRyKS52aWV3KCkucGluZygpKQoJCWV4Y2VwdCBFeGNlcHRpb24gYXMgZToKCQkJcHJpbnQoZidBIGNhbGwgZmFpbGVkOiB7dHlwZShlKS5fX25hbWVfX30nKQoAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/intercontract/call_view_emit.0_0_0.hash b/tests/cases/stable/py/intercontract/call_view_emit.0_0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_view_emit.0_0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/intercontract/call_view_iface.0.hash b/tests/cases/stable/py/intercontract/call_view_iface.0.hash new file mode 100644 index 000000000..59d2c3dc0 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_view_iface.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxIXAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcGFzcwoKCUBnbC5wdWJsaWMudmlldwoJZGVmIGZvbyhzZWxmLCBhLCBiKToKCQlwcmludCgnY29udHJhY3QgdG8uZm9vJykKCQlpbXBvcnQganNvbgoKCQlqc29uLmxvYWRzID0gMTEgICMgZXZpbCEKCQlyZXR1cm4gYSArIGIKAAAAAAAF diff --git a/tests/cases/stable/py/intercontract/call_view_iface.0_0.hash b/tests/cases/stable/py/intercontract/call_view_iface.0_0.hash new file mode 100644 index 000000000..5835cfec5 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_view_iface.0_0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxhdAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpAZ2wuY29udHJhY3QuaW50ZXJmYWNlCmNsYXNzIFRvSWZhY2U6CgljbGFzcyBWaWV3OgoJCWRlZiBmb28oc2VsZiwgYSwgYik6IC4uLgoKCWNsYXNzIFdyaXRlOgoJCXBhc3MKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmLCBhZGRyOiBBZGRyZXNzKToKCQlwcmludCgnY29udHJhY3QgZnJvbS5tYWluJykKCQlwcmludChUb0lmYWNlKGFkZHIpLnZpZXcoKS5mb28oMSwgMikpCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/py/intercontract/call_view_iface.0_0_0.hash b/tests/cases/stable/py/intercontract/call_view_iface.0_0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/intercontract/call_view_iface.0_0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/intercontract/deploy.0.hash b/tests/cases/stable/py/intercontract/deploy.0.hash new file mode 100644 index 000000000..e6d23347e --- /dev/null +++ b/tests/cases/stable/py/intercontract/deploy.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgw7XAAAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJZ2wuY29udHJhY3QuZGVwbG95KGNvZGU9J25vdCByZWFsbHkgYSBjb250cmFjdCcuZW5jb2RlKCd1dGYtOCcpKQoAAAAAAAU= diff --git a/tests/cases/stable/py/intercontract/deploy_salt.0.hash b/tests/cases/stable/py/intercontract/deploy_salt.0.hash new file mode 100644 index 000000000..b864725a5 --- /dev/null +++ b/tests/cases/stable/py/intercontract/deploy_salt.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxD4AAAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcmVzID0gZ2wuY29udHJhY3QuZGVwbG95KGNvZGU9J25vdCByZWFsbHkgYSBjb250cmFjdCcuZW5jb2RlKCd1dGYtOCcpLCBzYWx0X25vbmNlPTEpCgkJcHJpbnQocmVzKQoAAAAABQ== diff --git a/tests/cases/stable/py/intercontract/eth_call_view.0.hash b/tests/cases/stable/py/intercontract/eth_call_view.0.hash new file mode 100644 index 000000000..2f18c5b63 --- /dev/null +++ b/tests/cases/stable/py/intercontract/eth_call_view.0.hash @@ -0,0 +1 @@ +LRF0aG9zdCBmb3JiaWRkZW4AHRWjAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowIhueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALoAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYnoV50UNnwTpw9jS2Fao6ceN+gCB6iwSj9yTzi3zXr1gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDGoABAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCkBnbC5ldm0uY29udHJhY3RfaW50ZXJmYWNlCmNsYXNzIEdob3N0OgoJY2xhc3MgVmlldzoKCQlkZWYgdGVzdChzZWxmLCB4OiB1MjU2LCAvKSAtPiB1MjU2OiAuLi4KCgljbGFzcyBXcml0ZToKCQlwYXNzCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJZGVmIF9faW5pdF9fKHNlbGYpOgoJCXRyeToKCQkJR2hvc3QoQWRkcmVzcyhiJ1x4MzAnICogMjApKS52aWV3KCkudGVzdCgxMCkKCQlleGNlcHQgQmFzZUV4Y2VwdGlvbiBhcyBlOgoJCQlwcmludChmJ2V4cGVjdGVkIGVycm9yOiB7ZX0nKQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/intercontract/send_message.0.hash b/tests/cases/stable/py/intercontract/send_message.0.hash new file mode 100644 index 000000000..aeb7b5c19 --- /dev/null +++ b/tests/cases/stable/py/intercontract/send_message.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgw7UAAAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJZ2wuY29udHJhY3QuZ2V0X2F0KGdsLkFkZHJlc3MoYidceDMwJyAqIDIwKSkuZW1pdCgpLmZvbygxLCAyKQoAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/intercontract/send_message_eth.0.hash b/tests/cases/stable/py/intercontract/send_message_eth.0.hash new file mode 100644 index 000000000..4e7cc57ab --- /dev/null +++ b/tests/cases/stable/py/intercontract/send_message_eth.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxZYAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpAZ2wuZXZtLmNvbnRyYWN0X2ludGVyZmFjZQpjbGFzcyBHaG9zdDoKCWNsYXNzIFZpZXc6CgkJcGFzcwoKCWNsYXNzIFdyaXRlOgoJCWRlZiB0ZXN0KHNlbGYsIHg6IHUyNTYsIC8pIC0+IE5vbmU6IC4uLgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwcmludChzZWxmLmJhbGFuY2UpCgkJR2hvc3QoQWRkcmVzcyhiJ1x4MzAnICogMjApKS5lbWl0KHZhbHVlPTMwKS50ZXN0KDEwKQoAAAAABQ== diff --git a/tests/cases/stable/py/intercontract/send_message_on.0.hash b/tests/cases/stable/py/intercontract/send_message_on.0.hash new file mode 100644 index 000000000..6ef3c299a --- /dev/null +++ b/tests/cases/stable/py/intercontract/send_message_on.0.hash @@ -0,0 +1 @@ +LRFcZXhpdF9jb2RlIDEAHRWjAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowIhueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALoAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYnoV50UNnwTpw9jS2Fao6ceN+gCB6iwSj9yTzi3zXr1gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDFB8BAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYsIG9uOiBzdHIpOgoJCXRyeToKCQkJZ2wuY29udHJhY3QuZ2V0X2F0KGdsLkFkZHJlc3MoYidceDMwJyAqIDIwKSkuZW1pdChvbj1vbikuZm9vKDEsIDIpCgkJZXhjZXB0IFN5c3RlbUVycm9yIGFzIGU6CgkJCXByaW50KGUpCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/intercontract/send_message_on.0_0.hash b/tests/cases/stable/py/intercontract/send_message_on.0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/intercontract/send_message_on.0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/intercontract/send_message_on.0_0_0.hash b/tests/cases/stable/py/intercontract/send_message_on.0_0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/intercontract/send_message_on.0_0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/other/meth/method_init.0.hash b/tests/cases/stable/py/other/meth/method_init.0.hash new file mode 100644 index 000000000..5a3f58162 --- /dev/null +++ b/tests/cases/stable/py/other/meth/method_init.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyh8AgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcHJpbnQoJ2luaXQnKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBwdWIoc2VsZik6CgkJZXZhbCgicHJpbnQoJ2luaXQgZnJvbSBwdWIhJykiKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiByYmFjayhzZWxmKToKCQlnbC52bS5Vc2VyRXJyb3IuaW1tZWRpYXRlKCJuYWgsIEkgd29uJ3QgZXhlY3V0ZSIpCgoJZGVmIHByaXYoc2VsZik6CgkJZXZhbCgicHJpbnQoJ2luaXQgZnJvbSBwcml2IScpIikKCglAZ2wucHVibGljLndyaXRlCglkZWYgcmV0bihzZWxmKToKCQlyZXR1cm4geyd4JzogMTB9CgoJQGdsLnB1YmxpYy52aWV3CglkZWYgcmV0bl92aWV3KHNlbGYpOgoJCXJldHVybiB7J3gnOiAxMH0KCglAZ2wucHVibGljLndyaXRlCglkZWYgZGV0X3Zpb2woc2VsZik6CgkJZ2wubm9uZGV0LndlYi5yZW5kZXIoCgkJCSdodHRwczovL3Rlc3Qtc2VydmVyLmdlbmxheWVyLmNvbS9zdGF0aWMvZ2Vudm0vaGVsbG8uaHRtbCcsCgkJCW1vZGU9J3RleHQnLAoJCSkKBQ== diff --git a/tests/cases/stable/py/other/meth/method_init_wrong_name.0.hash b/tests/cases/stable/py/other/meth/method_init_wrong_name.0.hash new file mode 100644 index 000000000..5a3f58162 --- /dev/null +++ b/tests/cases/stable/py/other/meth/method_init_wrong_name.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyh8AgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcHJpbnQoJ2luaXQnKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBwdWIoc2VsZik6CgkJZXZhbCgicHJpbnQoJ2luaXQgZnJvbSBwdWIhJykiKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiByYmFjayhzZWxmKToKCQlnbC52bS5Vc2VyRXJyb3IuaW1tZWRpYXRlKCJuYWgsIEkgd29uJ3QgZXhlY3V0ZSIpCgoJZGVmIHByaXYoc2VsZik6CgkJZXZhbCgicHJpbnQoJ2luaXQgZnJvbSBwcml2IScpIikKCglAZ2wucHVibGljLndyaXRlCglkZWYgcmV0bihzZWxmKToKCQlyZXR1cm4geyd4JzogMTB9CgoJQGdsLnB1YmxpYy52aWV3CglkZWYgcmV0bl92aWV3KHNlbGYpOgoJCXJldHVybiB7J3gnOiAxMH0KCglAZ2wucHVibGljLndyaXRlCglkZWYgZGV0X3Zpb2woc2VsZik6CgkJZ2wubm9uZGV0LndlYi5yZW5kZXIoCgkJCSdodHRwczovL3Rlc3Qtc2VydmVyLmdlbmxheWVyLmNvbS9zdGF0aWMvZ2Vudm0vaGVsbG8uaHRtbCcsCgkJCW1vZGU9J3RleHQnLAoJCSkKBQ== diff --git a/tests/cases/stable/py/other/meth/method_public.0.hash b/tests/cases/stable/py/other/meth/method_public.0.hash new file mode 100644 index 000000000..5a3f58162 --- /dev/null +++ b/tests/cases/stable/py/other/meth/method_public.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyh8AgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcHJpbnQoJ2luaXQnKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBwdWIoc2VsZik6CgkJZXZhbCgicHJpbnQoJ2luaXQgZnJvbSBwdWIhJykiKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiByYmFjayhzZWxmKToKCQlnbC52bS5Vc2VyRXJyb3IuaW1tZWRpYXRlKCJuYWgsIEkgd29uJ3QgZXhlY3V0ZSIpCgoJZGVmIHByaXYoc2VsZik6CgkJZXZhbCgicHJpbnQoJ2luaXQgZnJvbSBwcml2IScpIikKCglAZ2wucHVibGljLndyaXRlCglkZWYgcmV0bihzZWxmKToKCQlyZXR1cm4geyd4JzogMTB9CgoJQGdsLnB1YmxpYy52aWV3CglkZWYgcmV0bl92aWV3KHNlbGYpOgoJCXJldHVybiB7J3gnOiAxMH0KCglAZ2wucHVibGljLndyaXRlCglkZWYgZGV0X3Zpb2woc2VsZik6CgkJZ2wubm9uZGV0LndlYi5yZW5kZXIoCgkJCSdodHRwczovL3Rlc3Qtc2VydmVyLmdlbmxheWVyLmNvbS9zdGF0aWMvZ2Vudm0vaGVsbG8uaHRtbCcsCgkJCW1vZGU9J3RleHQnLAoJCSkKBQ== diff --git a/tests/cases/stable/py/other/meth/method_public.0_0.hash b/tests/cases/stable/py/other/meth/method_public.0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/other/meth/method_public.0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/other/meth/method_retn.0.hash b/tests/cases/stable/py/other/meth/method_retn.0.hash new file mode 100644 index 000000000..5a3f58162 --- /dev/null +++ b/tests/cases/stable/py/other/meth/method_retn.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyh8AgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcHJpbnQoJ2luaXQnKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBwdWIoc2VsZik6CgkJZXZhbCgicHJpbnQoJ2luaXQgZnJvbSBwdWIhJykiKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiByYmFjayhzZWxmKToKCQlnbC52bS5Vc2VyRXJyb3IuaW1tZWRpYXRlKCJuYWgsIEkgd29uJ3QgZXhlY3V0ZSIpCgoJZGVmIHByaXYoc2VsZik6CgkJZXZhbCgicHJpbnQoJ2luaXQgZnJvbSBwcml2IScpIikKCglAZ2wucHVibGljLndyaXRlCglkZWYgcmV0bihzZWxmKToKCQlyZXR1cm4geyd4JzogMTB9CgoJQGdsLnB1YmxpYy52aWV3CglkZWYgcmV0bl92aWV3KHNlbGYpOgoJCXJldHVybiB7J3gnOiAxMH0KCglAZ2wucHVibGljLndyaXRlCglkZWYgZGV0X3Zpb2woc2VsZik6CgkJZ2wubm9uZGV0LndlYi5yZW5kZXIoCgkJCSdodHRwczovL3Rlc3Qtc2VydmVyLmdlbmxheWVyLmNvbS9zdGF0aWMvZ2Vudm0vaGVsbG8uaHRtbCcsCgkJCW1vZGU9J3RleHQnLAoJCSkKBQ== diff --git a/tests/cases/stable/py/other/meth/method_retn.0_0.hash b/tests/cases/stable/py/other/meth/method_retn.0_0.hash new file mode 100644 index 000000000..ac9183e6f --- /dev/null +++ b/tests/cases/stable/py/other/meth/method_retn.0_0.hash @@ -0,0 +1 @@ +LQEOAXhRAAUF diff --git a/tests/cases/stable/py/other/meth/method_retn_view.0.hash b/tests/cases/stable/py/other/meth/method_retn_view.0.hash new file mode 100644 index 000000000..5a3f58162 --- /dev/null +++ b/tests/cases/stable/py/other/meth/method_retn_view.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyh8AgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcHJpbnQoJ2luaXQnKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBwdWIoc2VsZik6CgkJZXZhbCgicHJpbnQoJ2luaXQgZnJvbSBwdWIhJykiKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiByYmFjayhzZWxmKToKCQlnbC52bS5Vc2VyRXJyb3IuaW1tZWRpYXRlKCJuYWgsIEkgd29uJ3QgZXhlY3V0ZSIpCgoJZGVmIHByaXYoc2VsZik6CgkJZXZhbCgicHJpbnQoJ2luaXQgZnJvbSBwcml2IScpIikKCglAZ2wucHVibGljLndyaXRlCglkZWYgcmV0bihzZWxmKToKCQlyZXR1cm4geyd4JzogMTB9CgoJQGdsLnB1YmxpYy52aWV3CglkZWYgcmV0bl92aWV3KHNlbGYpOgoJCXJldHVybiB7J3gnOiAxMH0KCglAZ2wucHVibGljLndyaXRlCglkZWYgZGV0X3Zpb2woc2VsZik6CgkJZ2wubm9uZGV0LndlYi5yZW5kZXIoCgkJCSdodHRwczovL3Rlc3Qtc2VydmVyLmdlbmxheWVyLmNvbS9zdGF0aWMvZ2Vudm0vaGVsbG8uaHRtbCcsCgkJCW1vZGU9J3RleHQnLAoJCSkKBQ== diff --git a/tests/cases/stable/py/other/meth/method_retn_view.0_0.hash b/tests/cases/stable/py/other/meth/method_retn_view.0_0.hash new file mode 100644 index 000000000..ac9183e6f --- /dev/null +++ b/tests/cases/stable/py/other/meth/method_retn_view.0_0.hash @@ -0,0 +1 @@ +LQEOAXhRAAUF diff --git a/tests/cases/stable/py/other/meth/method_rollback.0.hash b/tests/cases/stable/py/other/meth/method_rollback.0.hash new file mode 100644 index 000000000..5a3f58162 --- /dev/null +++ b/tests/cases/stable/py/other/meth/method_rollback.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyh8AgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcHJpbnQoJ2luaXQnKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBwdWIoc2VsZik6CgkJZXZhbCgicHJpbnQoJ2luaXQgZnJvbSBwdWIhJykiKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiByYmFjayhzZWxmKToKCQlnbC52bS5Vc2VyRXJyb3IuaW1tZWRpYXRlKCJuYWgsIEkgd29uJ3QgZXhlY3V0ZSIpCgoJZGVmIHByaXYoc2VsZik6CgkJZXZhbCgicHJpbnQoJ2luaXQgZnJvbSBwcml2IScpIikKCglAZ2wucHVibGljLndyaXRlCglkZWYgcmV0bihzZWxmKToKCQlyZXR1cm4geyd4JzogMTB9CgoJQGdsLnB1YmxpYy52aWV3CglkZWYgcmV0bl92aWV3KHNlbGYpOgoJCXJldHVybiB7J3gnOiAxMH0KCglAZ2wucHVibGljLndyaXRlCglkZWYgZGV0X3Zpb2woc2VsZik6CgkJZ2wubm9uZGV0LndlYi5yZW5kZXIoCgkJCSdodHRwczovL3Rlc3Qtc2VydmVyLmdlbmxheWVyLmNvbS9zdGF0aWMvZ2Vudm0vaGVsbG8uaHRtbCcsCgkJCW1vZGU9J3RleHQnLAoJCSkKBQ== diff --git a/tests/cases/stable/py/other/meth/method_rollback.0_0.hash b/tests/cases/stable/py/other/meth/method_rollback.0_0.hash new file mode 100644 index 000000000..ed0398513 --- /dev/null +++ b/tests/cases/stable/py/other/meth/method_rollback.0_0.hash @@ -0,0 +1 @@ +LQmkAW5haCwgSSB3b24ndCBleGVjdXRlAAUF diff --git a/tests/cases/stable/py/other/ret/returns.0.hash b/tests/cases/stable/py/other/ret/returns.0.hash new file mode 100644 index 000000000..959e3697a --- /dev/null +++ b/tests/cases/stable/py/other/ret/returns.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxqSAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmLCBpZHg6IGludCk6CgkJcmV0ID0gWwoJCQlBZGRyZXNzKGInXHgwMScgKiAyMCksCgkJCSdhYmMnLAoJCQkxMjMsCgkJCWIneHl6JywKCQkJVHJ1ZSwKCQkJTm9uZSwKCQkJRmFsc2UsCgkJCVtBZGRyZXNzKGInXHgwMicgKiAyMCksIEFkZHJlc3MoYidceDAzJyAqIDIwKV0sCgkJCXsnYSc6IDEsICdiJzogWzEsIDIsIDNdfSwKCQldCgkJcHJpbnQoZid7aWR4fSBbMC4uLntsZW4ocmV0KX0pJykKCQlyZXR1cm4gcmV0W2lkeF0KAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/other/ret/returns.0_0.hash b/tests/cases/stable/py/other/ret/returns.0_0.hash new file mode 100644 index 000000000..373e64783 --- /dev/null +++ b/tests/cases/stable/py/other/ret/returns.0_0.hash @@ -0,0 +1 @@ +LQEYAQEBAQEBAQEBAQEBAQEBAQEBAQEABQU= diff --git a/tests/cases/stable/py/other/ret/returns.1.hash b/tests/cases/stable/py/other/ret/returns.1.hash new file mode 100644 index 000000000..959e3697a --- /dev/null +++ b/tests/cases/stable/py/other/ret/returns.1.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxqSAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmLCBpZHg6IGludCk6CgkJcmV0ID0gWwoJCQlBZGRyZXNzKGInXHgwMScgKiAyMCksCgkJCSdhYmMnLAoJCQkxMjMsCgkJCWIneHl6JywKCQkJVHJ1ZSwKCQkJTm9uZSwKCQkJRmFsc2UsCgkJCVtBZGRyZXNzKGInXHgwMicgKiAyMCksIEFkZHJlc3MoYidceDAzJyAqIDIwKV0sCgkJCXsnYSc6IDEsICdiJzogWzEsIDIsIDNdfSwKCQldCgkJcHJpbnQoZid7aWR4fSBbMC4uLntsZW4ocmV0KX0pJykKCQlyZXR1cm4gcmV0W2lkeF0KAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/other/ret/returns.1_0.hash b/tests/cases/stable/py/other/ret/returns.1_0.hash new file mode 100644 index 000000000..fcc9cff46 --- /dev/null +++ b/tests/cases/stable/py/other/ret/returns.1_0.hash @@ -0,0 +1 @@ +LQEcYWJjAAUF diff --git a/tests/cases/stable/py/other/ret/returns.2.hash b/tests/cases/stable/py/other/ret/returns.2.hash new file mode 100644 index 000000000..959e3697a --- /dev/null +++ b/tests/cases/stable/py/other/ret/returns.2.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxqSAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmLCBpZHg6IGludCk6CgkJcmV0ID0gWwoJCQlBZGRyZXNzKGInXHgwMScgKiAyMCksCgkJCSdhYmMnLAoJCQkxMjMsCgkJCWIneHl6JywKCQkJVHJ1ZSwKCQkJTm9uZSwKCQkJRmFsc2UsCgkJCVtBZGRyZXNzKGInXHgwMicgKiAyMCksIEFkZHJlc3MoYidceDAzJyAqIDIwKV0sCgkJCXsnYSc6IDEsICdiJzogWzEsIDIsIDNdfSwKCQldCgkJcHJpbnQoZid7aWR4fSBbMC4uLntsZW4ocmV0KX0pJykKCQlyZXR1cm4gcmV0W2lkeF0KAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/other/ret/returns.2_0.hash b/tests/cases/stable/py/other/ret/returns.2_0.hash new file mode 100644 index 000000000..ae3321495 --- /dev/null +++ b/tests/cases/stable/py/other/ret/returns.2_0.hash @@ -0,0 +1 @@ +LQHZBwAFBQ== diff --git a/tests/cases/stable/py/other/ret/returns.3.hash b/tests/cases/stable/py/other/ret/returns.3.hash new file mode 100644 index 000000000..959e3697a --- /dev/null +++ b/tests/cases/stable/py/other/ret/returns.3.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxqSAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmLCBpZHg6IGludCk6CgkJcmV0ID0gWwoJCQlBZGRyZXNzKGInXHgwMScgKiAyMCksCgkJCSdhYmMnLAoJCQkxMjMsCgkJCWIneHl6JywKCQkJVHJ1ZSwKCQkJTm9uZSwKCQkJRmFsc2UsCgkJCVtBZGRyZXNzKGInXHgwMicgKiAyMCksIEFkZHJlc3MoYidceDAzJyAqIDIwKV0sCgkJCXsnYSc6IDEsICdiJzogWzEsIDIsIDNdfSwKCQldCgkJcHJpbnQoZid7aWR4fSBbMC4uLntsZW4ocmV0KX0pJykKCQlyZXR1cm4gcmV0W2lkeF0KAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/other/ret/returns.3_0.hash b/tests/cases/stable/py/other/ret/returns.3_0.hash new file mode 100644 index 000000000..1c55f7e94 --- /dev/null +++ b/tests/cases/stable/py/other/ret/returns.3_0.hash @@ -0,0 +1 @@ +LQEbeHl6AAUF diff --git a/tests/cases/stable/py/other/ret/returns.4.hash b/tests/cases/stable/py/other/ret/returns.4.hash new file mode 100644 index 000000000..959e3697a --- /dev/null +++ b/tests/cases/stable/py/other/ret/returns.4.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxqSAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmLCBpZHg6IGludCk6CgkJcmV0ID0gWwoJCQlBZGRyZXNzKGInXHgwMScgKiAyMCksCgkJCSdhYmMnLAoJCQkxMjMsCgkJCWIneHl6JywKCQkJVHJ1ZSwKCQkJTm9uZSwKCQkJRmFsc2UsCgkJCVtBZGRyZXNzKGInXHgwMicgKiAyMCksIEFkZHJlc3MoYidceDAzJyAqIDIwKV0sCgkJCXsnYSc6IDEsICdiJzogWzEsIDIsIDNdfSwKCQldCgkJcHJpbnQoZid7aWR4fSBbMC4uLntsZW4ocmV0KX0pJykKCQlyZXR1cm4gcmV0W2lkeF0KAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/other/ret/returns.4_0.hash b/tests/cases/stable/py/other/ret/returns.4_0.hash new file mode 100644 index 000000000..911179dae --- /dev/null +++ b/tests/cases/stable/py/other/ret/returns.4_0.hash @@ -0,0 +1 @@ +LQEQAAUF diff --git a/tests/cases/stable/py/other/ret/returns.5.hash b/tests/cases/stable/py/other/ret/returns.5.hash new file mode 100644 index 000000000..959e3697a --- /dev/null +++ b/tests/cases/stable/py/other/ret/returns.5.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxqSAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmLCBpZHg6IGludCk6CgkJcmV0ID0gWwoJCQlBZGRyZXNzKGInXHgwMScgKiAyMCksCgkJCSdhYmMnLAoJCQkxMjMsCgkJCWIneHl6JywKCQkJVHJ1ZSwKCQkJTm9uZSwKCQkJRmFsc2UsCgkJCVtBZGRyZXNzKGInXHgwMicgKiAyMCksIEFkZHJlc3MoYidceDAzJyAqIDIwKV0sCgkJCXsnYSc6IDEsICdiJzogWzEsIDIsIDNdfSwKCQldCgkJcHJpbnQoZid7aWR4fSBbMC4uLntsZW4ocmV0KX0pJykKCQlyZXR1cm4gcmV0W2lkeF0KAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/other/ret/returns.5_0.hash b/tests/cases/stable/py/other/ret/returns.5_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/other/ret/returns.5_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/other/ret/returns.6.hash b/tests/cases/stable/py/other/ret/returns.6.hash new file mode 100644 index 000000000..959e3697a --- /dev/null +++ b/tests/cases/stable/py/other/ret/returns.6.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxqSAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmLCBpZHg6IGludCk6CgkJcmV0ID0gWwoJCQlBZGRyZXNzKGInXHgwMScgKiAyMCksCgkJCSdhYmMnLAoJCQkxMjMsCgkJCWIneHl6JywKCQkJVHJ1ZSwKCQkJTm9uZSwKCQkJRmFsc2UsCgkJCVtBZGRyZXNzKGInXHgwMicgKiAyMCksIEFkZHJlc3MoYidceDAzJyAqIDIwKV0sCgkJCXsnYSc6IDEsICdiJzogWzEsIDIsIDNdfSwKCQldCgkJcHJpbnQoZid7aWR4fSBbMC4uLntsZW4ocmV0KX0pJykKCQlyZXR1cm4gcmV0W2lkeF0KAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/other/ret/returns.6_0.hash b/tests/cases/stable/py/other/ret/returns.6_0.hash new file mode 100644 index 000000000..f9aa455c2 --- /dev/null +++ b/tests/cases/stable/py/other/ret/returns.6_0.hash @@ -0,0 +1 @@ +LQEIAAUF diff --git a/tests/cases/stable/py/other/ret/returns.7.hash b/tests/cases/stable/py/other/ret/returns.7.hash new file mode 100644 index 000000000..959e3697a --- /dev/null +++ b/tests/cases/stable/py/other/ret/returns.7.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxqSAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmLCBpZHg6IGludCk6CgkJcmV0ID0gWwoJCQlBZGRyZXNzKGInXHgwMScgKiAyMCksCgkJCSdhYmMnLAoJCQkxMjMsCgkJCWIneHl6JywKCQkJVHJ1ZSwKCQkJTm9uZSwKCQkJRmFsc2UsCgkJCVtBZGRyZXNzKGInXHgwMicgKiAyMCksIEFkZHJlc3MoYidceDAzJyAqIDIwKV0sCgkJCXsnYSc6IDEsICdiJzogWzEsIDIsIDNdfSwKCQldCgkJcHJpbnQoZid7aWR4fSBbMC4uLntsZW4ocmV0KX0pJykKCQlyZXR1cm4gcmV0W2lkeF0KAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/other/ret/returns.7_0.hash b/tests/cases/stable/py/other/ret/returns.7_0.hash new file mode 100644 index 000000000..a870ecc23 --- /dev/null +++ b/tests/cases/stable/py/other/ret/returns.7_0.hash @@ -0,0 +1 @@ +LQEVGAICAgICAgICAgICAgICAgICAgICGAMDAwMDAwMDAwMDAwMDAwMDAwMDAAUF diff --git a/tests/cases/stable/py/other/ret/returns.8.hash b/tests/cases/stable/py/other/ret/returns.8.hash new file mode 100644 index 000000000..959e3697a --- /dev/null +++ b/tests/cases/stable/py/other/ret/returns.8.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxqSAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmLCBpZHg6IGludCk6CgkJcmV0ID0gWwoJCQlBZGRyZXNzKGInXHgwMScgKiAyMCksCgkJCSdhYmMnLAoJCQkxMjMsCgkJCWIneHl6JywKCQkJVHJ1ZSwKCQkJTm9uZSwKCQkJRmFsc2UsCgkJCVtBZGRyZXNzKGInXHgwMicgKiAyMCksIEFkZHJlc3MoYidceDAzJyAqIDIwKV0sCgkJCXsnYSc6IDEsICdiJzogWzEsIDIsIDNdfSwKCQldCgkJcHJpbnQoZid7aWR4fSBbMC4uLntsZW4ocmV0KX0pJykKCQlyZXR1cm4gcmV0W2lkeF0KAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/other/ret/returns.8_0.hash b/tests/cases/stable/py/other/ret/returns.8_0.hash new file mode 100644 index 000000000..c2ca05777 --- /dev/null +++ b/tests/cases/stable/py/other/ret/returns.8_0.hash @@ -0,0 +1 @@ +LQEWAWEJAWIdCREZAAUF diff --git a/tests/cases/stable/py/other/ret/returns.9.hash b/tests/cases/stable/py/other/ret/returns.9.hash new file mode 100644 index 000000000..959e3697a --- /dev/null +++ b/tests/cases/stable/py/other/ret/returns.9.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxqSAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmLCBpZHg6IGludCk6CgkJcmV0ID0gWwoJCQlBZGRyZXNzKGInXHgwMScgKiAyMCksCgkJCSdhYmMnLAoJCQkxMjMsCgkJCWIneHl6JywKCQkJVHJ1ZSwKCQkJTm9uZSwKCQkJRmFsc2UsCgkJCVtBZGRyZXNzKGInXHgwMicgKiAyMCksIEFkZHJlc3MoYidceDAzJyAqIDIwKV0sCgkJCXsnYSc6IDEsICdiJzogWzEsIDIsIDNdfSwKCQldCgkJcHJpbnQoZid7aWR4fSBbMC4uLntsZW4ocmV0KX0pJykKCQlyZXR1cm4gcmV0W2lkeF0KAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/other/ret/returns.9_0.hash b/tests/cases/stable/py/other/ret/returns.9_0.hash new file mode 100644 index 000000000..131eae252 --- /dev/null +++ b/tests/cases/stable/py/other/ret/returns.9_0.hash @@ -0,0 +1 @@ +LRFcZXhpdF9jb2RlIDEABQU= diff --git a/tests/cases/stable/py/pitfalls/multi_contract.0.hash b/tests/cases/stable/py/pitfalls/multi_contract.0.hash new file mode 100644 index 000000000..11d165937 --- /dev/null +++ b/tests/cases/stable/py/pitfalls/multi_contract.0.hash @@ -0,0 +1 @@ +LRFcZXhpdF9jb2RlIDEAFRWjAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDEgEBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0MShnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcHJpbnQoJ2hlbGxvIHdvcmxkJykKCgpjbGFzcyBDb250cmFjdDIoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJZGVmIF9faW5pdF9fKHNlbGYpOgoJCXByaW50KCdoZWxsbyB3b3JsZCcpCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/pitfalls/pub_ctor.0.hash b/tests/cases/stable/py/pitfalls/pub_ctor.0.hash new file mode 100644 index 000000000..707cb2fc3 --- /dev/null +++ b/tests/cases/stable/py/pitfalls/pub_ctor.0.hash @@ -0,0 +1 @@ +LRFcZXhpdF9jb2RlIDEAHRWjAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowIhueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALoAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYnoV50UNnwTpw9jS2Fao6ceN+gCB6iwSj9yTzi3zXr1gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDDr0AAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwcmludCgnaGVsbG8gd29ybGQnKQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/pitfalls/store_proxy.0.hash b/tests/cases/stable/py/pitfalls/store_proxy.0.hash new file mode 100644 index 000000000..9e7b812d3 --- /dev/null +++ b/tests/cases/stable/py/pitfalls/store_proxy.0.hash @@ -0,0 +1 @@ +LQEAADUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCRqtO0me0YTFGMKUIKVN5qk+zOkFIIu6dcvDrLiymbsAAAAAAgwISAAAA4m1FZwAAAAAyeQYAAAAAAAAAAAAAAAAAAAAAABWjAroAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELAAAAAIMkNQIAACMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCmZyb20gZ2VubGF5ZXIuc3RvcmFnZSBpbXBvcnQgYWxsb3cKCmZyb20gZGF0YWNsYXNzZXMgaW1wb3J0IGRhdGFjbGFzcwppbXBvcnQgZGF0ZXRpbWUKCgpAYWxsb3cKQGRhdGFjbGFzcwpjbGFzcyBVc2VyOgoJbmFtZTogc3RyCgliaXJ0aGRheTogZGF0ZXRpbWUuZGF0ZXRpbWUKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6Cgl1c2VyczogZ2wuRHluQXJyYXlbVXNlcl0KCglkZWYgX19pbml0X18oc2VsZik6CgkJc2VsZi51c2Vycy5hcHBlbmQoVXNlcignQWRhJywgZGF0ZXRpbWUuZGF0ZXRpbWUubm93KCkpKQoJCXVzZXIgPSBzZWxmLnVzZXJzWy0xXQoJCXNlbGYudXNlcnNbLTFdID0gVXNlcignRGVmaW5pdGVseSBub3QgQWRhJywgZGF0ZXRpbWUuZGF0ZXRpbWUubm93KCkpCgkJcHJpbnQodXNlci5uYW1lKQoJCWFzc2VydCB1c2VyLm5hbWUgPT0gJ0RlZmluaXRlbHkgbm90IEFkYScgICMgdGhpcyBpcyB0cnVlIQoAAAAAAAAAFaMC4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhecAAAAAgwIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAvC/CNTNsNC9yOvuCNfiE8+cb20NpEyVEFeSNxzeGgcsAAAAAIMCRGVmaW5pdGVseSBub3QgQWRhAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/py/rollbacks/call_view.0.hash b/tests/cases/stable/py/rollbacks/call_view.0.hash new file mode 100644 index 000000000..d39621377 --- /dev/null +++ b/tests/cases/stable/py/rollbacks/call_view.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxIcAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcGFzcwoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBmb28oc2VsZiwgYSwgYik6CgkJcHJpbnQoJ2NvbnRyYWN0IHRvLmZvbycpCgkJZ2wudm0uVXNlckVycm9yLmltbWVkaWF0ZShmIm5haCwgSSB3b24ndCBleGVjdXRlIHthICsgYn0iKQoF diff --git a/tests/cases/stable/py/rollbacks/call_view.0_0.hash b/tests/cases/stable/py/rollbacks/call_view.0_0.hash new file mode 100644 index 000000000..7b37b0469 --- /dev/null +++ b/tests/cases/stable/py/rollbacks/call_view.0_0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxqIAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcGFzcwoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYsIGFkZHI6IEFkZHJlc3MpOgoJCXByaW50KCdjb250cmFjdCBmcm9tLm1haW4nKQoJCXRyeToKCQkJcmVzID0gZ2wuY29udHJhY3QuZ2V0X2F0KGFkZHIpLnZpZXcoKS5mb28oMSwgMikuZ2V0KCkKCQlleGNlcHQgZ2wudm0uVXNlckVycm9yIGFzIHI6CgkJCXByaW50KCdoYW5kbGVkJywgci5kYXRhKQoJCWVsc2U6CgkJCXByaW50KHJlcykKCQkJZXhpdCgxKQoAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/rollbacks/call_view.0_0_0.hash b/tests/cases/stable/py/rollbacks/call_view.0_0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/rollbacks/call_view.0_0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/rollbacks/calldata_rollback.0.hash b/tests/cases/stable/py/rollbacks/calldata_rollback.0.hash new file mode 100644 index 000000000..2521f2596 --- /dev/null +++ b/tests/cases/stable/py/rollbacks/calldata_rollback.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxQjAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcGFzcwoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBmb28oc2VsZiwgYSwgYik6CgkJcHJpbnQoJ2NvbnRyYWN0IHRvLmZvbycpCgkJZ2wudm0uVXNlckVycm9yLmltbWVkaWF0ZSh7J2Vycm9yJzogJ3NvbWVfZXJyb3InLCAnY29kZSc6IGEgKyBifSkKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/rollbacks/calldata_rollback.0_0.hash b/tests/cases/stable/py/rollbacks/calldata_rollback.0_0.hash new file mode 100644 index 000000000..7b37b0469 --- /dev/null +++ b/tests/cases/stable/py/rollbacks/calldata_rollback.0_0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxqIAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcGFzcwoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYsIGFkZHI6IEFkZHJlc3MpOgoJCXByaW50KCdjb250cmFjdCBmcm9tLm1haW4nKQoJCXRyeToKCQkJcmVzID0gZ2wuY29udHJhY3QuZ2V0X2F0KGFkZHIpLnZpZXcoKS5mb28oMSwgMikuZ2V0KCkKCQlleGNlcHQgZ2wudm0uVXNlckVycm9yIGFzIHI6CgkJCXByaW50KCdoYW5kbGVkJywgci5kYXRhKQoJCWVsc2U6CgkJCXByaW50KHJlcykKCQkJZXhpdCgxKQoAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/rollbacks/calldata_rollback.0_0_0.hash b/tests/cases/stable/py/rollbacks/calldata_rollback.0_0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/rollbacks/calldata_rollback.0_0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/rollbacks/nondet.0.hash b/tests/cases/stable/py/rollbacks/nondet.0.hash new file mode 100644 index 000000000..6d2aa963e --- /dev/null +++ b/tests/cases/stable/py/rollbacks/nondet.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxhrAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJdHJ5OgoKCQkJZGVmIHJ1bigpOgoJCQkJZ2wudm0uVXNlckVycm9yLmltbWVkaWF0ZSgibmFoLCBJIHdvbid0IGV4ZWN1dGUiKQoKCQkJcmVzID0gZ2wuZXFfcHJpbmNpcGxlLnN0cmljdF9lcShydW4pLmdldCgpCgkJZXhjZXB0IGdsLnZtLlVzZXJFcnJvciBhcyByOgoJCQlwcmludCgnaGFuZGxlZCcsIHIuZGF0YSkKCQllbHNlOgoJCQlwcmludChyZXMpCgkJCWV4aXQoMSkKAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/py/rollbacks/simple.0.hash b/tests/cases/stable/py/rollbacks/simple.0.hash new file mode 100644 index 000000000..b4c91f659 --- /dev/null +++ b/tests/cases/stable/py/rollbacks/simple.0.hash @@ -0,0 +1 @@ +LQmkAW5haCwgSSB3b24ndCBleGVjdXRlAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgw7IAAAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJZ2wudm0uVXNlckVycm9yLmltbWVkaWF0ZSgibmFoLCBJIHdvbid0IGV4ZWN1dGUiKQoAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/sandbox/det/s/assign-json.0.hash b/tests/cases/stable/py/sandbox/det/s/assign-json.0.hash new file mode 100644 index 000000000..a2f14af61 --- /dev/null +++ b/tests/cases/stable/py/sandbox/det/s/assign-json.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxQgAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCmltcG9ydCBqc29uCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG1haW4oc2VsZiwgZXY6IHN0cik6CgkJZ2xiID0gZ2xvYmFscygpCgkJcHJpbnQoZid7Z2wudm0uc3Bhd25fc2FuZGJveChsYW1iZGE6IGV2YWwoZXYsIGdsYikpfScpCgkJcHJpbnQoanNvbi5sb2Fkcy5fX25hbWVfXykKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/sandbox/det/s/assign-json.0_0.hash b/tests/cases/stable/py/sandbox/det/s/assign-json.0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/sandbox/det/s/assign-json.0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/sandbox/det/s/exit.0.hash b/tests/cases/stable/py/sandbox/det/s/exit.0.hash new file mode 100644 index 000000000..a2f14af61 --- /dev/null +++ b/tests/cases/stable/py/sandbox/det/s/exit.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxQgAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCmltcG9ydCBqc29uCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG1haW4oc2VsZiwgZXY6IHN0cik6CgkJZ2xiID0gZ2xvYmFscygpCgkJcHJpbnQoZid7Z2wudm0uc3Bhd25fc2FuZGJveChsYW1iZGE6IGV2YWwoZXYsIGdsYikpfScpCgkJcHJpbnQoanNvbi5sb2Fkcy5fX25hbWVfXykKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/sandbox/det/s/exit.0_0.hash b/tests/cases/stable/py/sandbox/det/s/exit.0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/sandbox/det/s/exit.0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/sandbox/det/s/print.0.hash b/tests/cases/stable/py/sandbox/det/s/print.0.hash new file mode 100644 index 000000000..a2f14af61 --- /dev/null +++ b/tests/cases/stable/py/sandbox/det/s/print.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxQgAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCmltcG9ydCBqc29uCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG1haW4oc2VsZiwgZXY6IHN0cik6CgkJZ2xiID0gZ2xvYmFscygpCgkJcHJpbnQoZid7Z2wudm0uc3Bhd25fc2FuZGJveChsYW1iZGE6IGV2YWwoZXYsIGdsYikpfScpCgkJcHJpbnQoanNvbi5sb2Fkcy5fX25hbWVfXykKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/sandbox/det/s/print.0_0.hash b/tests/cases/stable/py/sandbox/det/s/print.0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/sandbox/det/s/print.0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/sandbox/det/s/rollback.0.hash b/tests/cases/stable/py/sandbox/det/s/rollback.0.hash new file mode 100644 index 000000000..a2f14af61 --- /dev/null +++ b/tests/cases/stable/py/sandbox/det/s/rollback.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxQgAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCmltcG9ydCBqc29uCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG1haW4oc2VsZiwgZXY6IHN0cik6CgkJZ2xiID0gZ2xvYmFscygpCgkJcHJpbnQoZid7Z2wudm0uc3Bhd25fc2FuZGJveChsYW1iZGE6IGV2YWwoZXYsIGdsYikpfScpCgkJcHJpbnQoanNvbi5sb2Fkcy5fX25hbWVfXykKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/sandbox/det/s/rollback.0_0.hash b/tests/cases/stable/py/sandbox/det/s/rollback.0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/sandbox/det/s/rollback.0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/sandbox/det/s/sandbox.0.hash b/tests/cases/stable/py/sandbox/det/s/sandbox.0.hash new file mode 100644 index 000000000..a2f14af61 --- /dev/null +++ b/tests/cases/stable/py/sandbox/det/s/sandbox.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxQgAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCmltcG9ydCBqc29uCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG1haW4oc2VsZiwgZXY6IHN0cik6CgkJZ2xiID0gZ2xvYmFscygpCgkJcHJpbnQoZid7Z2wudm0uc3Bhd25fc2FuZGJveChsYW1iZGE6IGV2YWwoZXYsIGdsYikpfScpCgkJcHJpbnQoanNvbi5sb2Fkcy5fX25hbWVfXykKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/py/sandbox/det/s/sandbox.0_0.hash b/tests/cases/stable/py/sandbox/det/s/sandbox.0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/sandbox/det/s/sandbox.0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/sandbox/det/sandbox_write.0.hash b/tests/cases/stable/py/sandbox/det/sandbox_write.0.hash new file mode 100644 index 000000000..b1c3c24a8 --- /dev/null +++ b/tests/cases/stable/py/sandbox/det/sandbox_write.0.hash @@ -0,0 +1 @@ +LQEAACUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxh2AQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0IHU4CgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJY291bnRlcjogdTgKCglkZWYgX19pbml0X18oc2VsZik6CgkJcHJpbnQoZidoZWxsbyB3b3JsZCB7c2VsZi5jb3VudGVyfScpCgoJCWRlZiBzYigpOgoJCQlzZWxmLmNvdW50ZXIgKz0gMQoKCQlwcmludChmJ2NvdW50ZXIgYmVmb3JlOiB7c2VsZi5jb3VudGVyfScpCgkJZ2wudm0uc3Bhd25fc2FuZGJveChzYiwgYWxsb3dfd3JpdGVfc3RvcmFnZT1UcnVlKQoJCXByaW50KGYnY291bnRlciBhZnRlcjoge3NlbGYuY291bnRlcn0nKQoAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/sandbox/non-det/s/assign-json.0.hash b/tests/cases/stable/py/sandbox/non-det/s/assign-json.0.hash new file mode 100644 index 000000000..c0d168136 --- /dev/null +++ b/tests/cases/stable/py/sandbox/non-det/s/assign-json.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxZcAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCmltcG9ydCBqc29uCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG1haW4oc2VsZiwgZXY6IHN0cik6CgkJZGVmIHJ1bl9uZGV0KCk6CgkJCWdsYiA9IGdsb2JhbHMoKQoJCQlwcmludChmJ3tnbC52bS5zcGF3bl9zYW5kYm94KGxhbWJkYTogZXZhbChldiwgZ2xiKSl9JykKCQkJcHJpbnQoanNvbi5sb2Fkcy5fX25hbWVfXykKCgkJZ2wuZXFfcHJpbmNpcGxlLnN0cmljdF9lcShydW5fbmRldCkKBQ== diff --git a/tests/cases/stable/py/sandbox/non-det/s/assign-json.0_0.hash b/tests/cases/stable/py/sandbox/non-det/s/assign-json.0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/sandbox/non-det/s/assign-json.0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/sandbox/non-det/s/exit.0.hash b/tests/cases/stable/py/sandbox/non-det/s/exit.0.hash new file mode 100644 index 000000000..c0d168136 --- /dev/null +++ b/tests/cases/stable/py/sandbox/non-det/s/exit.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxZcAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCmltcG9ydCBqc29uCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG1haW4oc2VsZiwgZXY6IHN0cik6CgkJZGVmIHJ1bl9uZGV0KCk6CgkJCWdsYiA9IGdsb2JhbHMoKQoJCQlwcmludChmJ3tnbC52bS5zcGF3bl9zYW5kYm94KGxhbWJkYTogZXZhbChldiwgZ2xiKSl9JykKCQkJcHJpbnQoanNvbi5sb2Fkcy5fX25hbWVfXykKCgkJZ2wuZXFfcHJpbmNpcGxlLnN0cmljdF9lcShydW5fbmRldCkKBQ== diff --git a/tests/cases/stable/py/sandbox/non-det/s/exit.0_0.hash b/tests/cases/stable/py/sandbox/non-det/s/exit.0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/sandbox/non-det/s/exit.0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/sandbox/non-det/s/print.0.hash b/tests/cases/stable/py/sandbox/non-det/s/print.0.hash new file mode 100644 index 000000000..c0d168136 --- /dev/null +++ b/tests/cases/stable/py/sandbox/non-det/s/print.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxZcAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCmltcG9ydCBqc29uCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG1haW4oc2VsZiwgZXY6IHN0cik6CgkJZGVmIHJ1bl9uZGV0KCk6CgkJCWdsYiA9IGdsb2JhbHMoKQoJCQlwcmludChmJ3tnbC52bS5zcGF3bl9zYW5kYm94KGxhbWJkYTogZXZhbChldiwgZ2xiKSl9JykKCQkJcHJpbnQoanNvbi5sb2Fkcy5fX25hbWVfXykKCgkJZ2wuZXFfcHJpbmNpcGxlLnN0cmljdF9lcShydW5fbmRldCkKBQ== diff --git a/tests/cases/stable/py/sandbox/non-det/s/print.0_0.hash b/tests/cases/stable/py/sandbox/non-det/s/print.0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/sandbox/non-det/s/print.0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/sandbox/non-det/s/rollback.0.hash b/tests/cases/stable/py/sandbox/non-det/s/rollback.0.hash new file mode 100644 index 000000000..c0d168136 --- /dev/null +++ b/tests/cases/stable/py/sandbox/non-det/s/rollback.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxZcAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCmltcG9ydCBqc29uCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG1haW4oc2VsZiwgZXY6IHN0cik6CgkJZGVmIHJ1bl9uZGV0KCk6CgkJCWdsYiA9IGdsb2JhbHMoKQoJCQlwcmludChmJ3tnbC52bS5zcGF3bl9zYW5kYm94KGxhbWJkYTogZXZhbChldiwgZ2xiKSl9JykKCQkJcHJpbnQoanNvbi5sb2Fkcy5fX25hbWVfXykKCgkJZ2wuZXFfcHJpbmNpcGxlLnN0cmljdF9lcShydW5fbmRldCkKBQ== diff --git a/tests/cases/stable/py/sandbox/non-det/s/rollback.0_0.hash b/tests/cases/stable/py/sandbox/non-det/s/rollback.0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/py/sandbox/non-det/s/rollback.0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/py/schemas/complex_types.0.hash b/tests/cases/stable/py/schemas/complex_types.0.hash new file mode 100644 index 000000000..af68583d7 --- /dev/null +++ b/tests/cases/stable/py/schemas/complex_types.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyhoAgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKaW1wb3J0IHR5cGluZwoKCmNsYXNzIE15VERpY3QodHlwaW5nLlR5cGVkRGljdCk6CglhOiBpbnQKCWI6IHN0cgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwYXNzCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG9wdCgKCQlzZWxmLCBhMTogbGlzdCB8IE5vbmUsIGEyOiB0eXBpbmcuVW5pb25bc3RyLCBieXRlc10sIGEzOiB0eXBpbmcuT3B0aW9uYWxbc3RyXQoJKToKCQlwYXNzCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGxzdCgKCQlzZWxmLCBhMTogbGlzdFtzdHJdLCBhMjogdHlwaW5nLlNlcXVlbmNlW3N0cl0sIGEzOiB0eXBpbmcuTXV0YWJsZVNlcXVlbmNlW2ludF0KCSk6CgkJcGFzcwoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBkaWN0KAoJCXNlbGYsCgkJYTE6IGRpY3Rbc3RyLCBpbnRdLAoJCWEyOiB0eXBpbmcuTWFwcGluZ1tzdHIsIHN0cl0sCgkJYTM6IHR5cGluZy5NdXRhYmxlTWFwcGluZ1tzdHIsIGludCB8IHN0ciB8IE5vbmVdLAoJKToKCQlwYXNzCgAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/schemas/complex_types.0_0.hash b/tests/cases/stable/py/schemas/complex_types.0_0.hash new file mode 100644 index 000000000..58efe808f --- /dev/null +++ b/tests/cases/stable/py/schemas/complex_types.0_0.hash @@ -0,0 +1 @@ +LQH0InsiY3RvciI6eyJwYXJhbXMiOltdLCJrd3BhcmFtcyI6e319LCJtZXRob2RzIjp7ImRpY3QiOnsicGFyYW1zIjpbWyJhMSIseyIkZGljdCI6ImludCJ9XSxbImEyIix7IiRkaWN0Ijoic3RyaW5nIn1dLFsiYTMiLHsiJGRpY3QiOnsiJG9yIjpbImludCIsInN0cmluZyIsIm51bGwiXX19XV0sImt3cGFyYW1zIjp7fSwicmVhZG9ubHkiOmZhbHNlLCJyZXQiOiJhbnkiLCJwYXlhYmxlIjpmYWxzZX0sImxzdCI6eyJwYXJhbXMiOltbImExIixbeyIkcmVwIjoic3RyaW5nIn1dXSxbImEyIixbeyIkcmVwIjoic3RyaW5nIn1dXSxbImEzIixbeyIkcmVwIjoiaW50In1dXV0sImt3cGFyYW1zIjp7fSwicmVhZG9ubHkiOmZhbHNlLCJyZXQiOiJhbnkiLCJwYXlhYmxlIjpmYWxzZX0sIm9wdCI6eyJwYXJhbXMiOltbImExIix7IiRvciI6WyJhcnJheSIsIm51bGwiXX1dLFsiYTIiLHsiJG9yIjpbInN0cmluZyIsImJ5dGVzIl19XSxbImEzIix7IiRvciI6WyJzdHJpbmciLCJudWxsIl19XV0sImt3cGFyYW1zIjp7fSwicmVhZG9ubHkiOmZhbHNlLCJyZXQiOiJhbnkiLCJwYXlhYmxlIjpmYWxzZX19fQAFBQ== diff --git a/tests/cases/stable/py/schemas/prim_types.0.hash b/tests/cases/stable/py/schemas/prim_types.0.hash new file mode 100644 index 000000000..c518842a0 --- /dev/null +++ b/tests/cases/stable/py/schemas/prim_types.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxhjAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCmltcG9ydCB0eXBpbmcKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcGFzcwoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBmb28oc2VsZiwgYTE6IGludCwgYTI6IE5vbmUsIGEzOiBib29sLCBhNDogc3RyLCBhNTogYnl0ZXMsIGE2OiBBZGRyZXNzKToKCQlwYXNzCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGVyYXNlZChzZWxmLCBhMTogbGlzdCwgYTI6IGRpY3QsIGEzOiB0eXBpbmcuQW55KToKCQlwYXNzCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/py/schemas/prim_types.0_0.hash b/tests/cases/stable/py/schemas/prim_types.0_0.hash new file mode 100644 index 000000000..521cc2e09 --- /dev/null +++ b/tests/cases/stable/py/schemas/prim_types.0_0.hash @@ -0,0 +1 @@ +LQGUFXsiY3RvciI6eyJwYXJhbXMiOltdLCJrd3BhcmFtcyI6e319LCJtZXRob2RzIjp7ImVyYXNlZCI6eyJwYXJhbXMiOltbImExIiwiYXJyYXkiXSxbImEyIiwiZGljdCJdLFsiYTMiLCJhbnkiXV0sImt3cGFyYW1zIjp7fSwicmVhZG9ubHkiOmZhbHNlLCJyZXQiOiJhbnkiLCJwYXlhYmxlIjpmYWxzZX0sImZvbyI6eyJwYXJhbXMiOltbImExIiwiaW50Il0sWyJhMiIsIm51bGwiXSxbImEzIiwiYm9vbCJdLFsiYTQiLCJzdHJpbmciXSxbImE1IiwiYnl0ZXMiXSxbImE2IiwiYWRkcmVzcyJdXSwia3dwYXJhbXMiOnt9LCJyZWFkb25seSI6ZmFsc2UsInJldCI6ImFueSIsInBheWFibGUiOmZhbHNlfX19AAUF diff --git a/tests/cases/stable/py/schemas/ret-float.0.hash b/tests/cases/stable/py/schemas/ret-float.0.hash new file mode 100644 index 000000000..637307c05 --- /dev/null +++ b/tests/cases/stable/py/schemas/ret-float.0.hash @@ -0,0 +1 @@ +LRFcZXhpdF9jb2RlIDEAHRWjAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowIhueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALoAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYnoV50UNnwTpw9jS2Fao6ceN+gCB6iwSj9yTzi3zXr1gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDEN4AAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmLCBmb28sIGJhcik6CgkJcGFzcwoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBmb28oc2VsZikgLT4gZmxvYXQ6CgkJcmV0dXJuIDAuMAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/py/schemas/ret-float.0_0.hash b/tests/cases/stable/py/schemas/ret-float.0_0.hash new file mode 100644 index 000000000..131eae252 --- /dev/null +++ b/tests/cases/stable/py/schemas/ret-float.0_0.hash @@ -0,0 +1 @@ +LRFcZXhpdF9jb2RlIDEABQU= diff --git a/tests/cases/stable/py/schemas/ret-tuple.0.hash b/tests/cases/stable/py/schemas/ret-tuple.0.hash new file mode 100644 index 000000000..4cd1df53b --- /dev/null +++ b/tests/cases/stable/py/schemas/ret-tuple.0.hash @@ -0,0 +1 @@ +LRFcZXhpdF9jb2RlIDEAHRWjAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowIhueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALoAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYnoV50UNnwTpw9jS2Fao6ceN+gCB6iwSj9yTzi3zXr1gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDFC8BAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmLCBmb28sIGJhcik6CgkJcGFzcwoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBmb28oc2VsZikgLT4gdHVwbGVbaW50LCBpbnRdOgoJCXJldHVybiAoMSwgMikKCglAZ2wucHVibGljLndyaXRlCglkZWYgYmFyKHNlbGYpIC0+IHR1cGxlW2ludCwgLi4uXToKCQlyZXR1cm4gKDEsKQoAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/py/schemas/ret-tuple.0_0.hash b/tests/cases/stable/py/schemas/ret-tuple.0_0.hash new file mode 100644 index 000000000..a47bd9db2 --- /dev/null +++ b/tests/cases/stable/py/schemas/ret-tuple.0_0.hash @@ -0,0 +1 @@ +LQHkD3siY3RvciI6eyJwYXJhbXMiOltbImZvbyIsImFueSJdLFsiYmFyIiwiYW55Il1dLCJrd3BhcmFtcyI6e319LCJtZXRob2RzIjp7ImJhciI6eyJwYXJhbXMiOltdLCJrd3BhcmFtcyI6e30sInJlYWRvbmx5IjpmYWxzZSwicmV0IjpbeyIkcmVwIjoiaW50In1dLCJwYXlhYmxlIjpmYWxzZX0sImZvbyI6eyJwYXJhbXMiOltdLCJrd3BhcmFtcyI6e30sInJlYWRvbmx5IjpmYWxzZSwicmV0IjpbImludCIsImludCJdLCJwYXlhYmxlIjpmYWxzZX19fQAFBQ== diff --git a/tests/cases/stable/py/schemas/ret.0.hash b/tests/cases/stable/py/schemas/ret.0.hash new file mode 100644 index 000000000..694e62810 --- /dev/null +++ b/tests/cases/stable/py/schemas/ret.0.hash @@ -0,0 +1 @@ +LRFcZXhpdF9jb2RlIDEAHRWjAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowIhueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALoAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYnoV50UNnwTpw9jS2Fao6ceN+gCB6iwSj9yTzi3zXr1gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDHKEBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmLCBmb28sIGJhcik6CgkJcGFzcwoKCUBnbC5wdWJsaWMudmlldwoJZGVmIGZvbyhzZWxmKToKCQlwYXNzCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIHBvcyhzZWxmLCB4LCB5KToKCQlwYXNzCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGt3KHNlbGYsICosIHgsIHkpOgoJCXBhc3MKCglAZ2wucHVibGljLndyaXRlCglkZWYgbWl4ZWQoc2VsZiwgYSwgYiwgKiwgeCwgeSk6CgkJcGFzcwoKCUBnbC5wdWJsaWMud3JpdGUucGF5YWJsZQoJZGVmIHBheWFibGUoc2VsZik6CgkJcGFzcwoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/py/schemas/ret.0_0.hash b/tests/cases/stable/py/schemas/ret.0_0.hash new file mode 100644 index 000000000..5f76c4b8b --- /dev/null +++ b/tests/cases/stable/py/schemas/ret.0_0.hash @@ -0,0 +1 @@ +LQHsIXsiY3RvciI6eyJwYXJhbXMiOltbImZvbyIsImFueSJdLFsiYmFyIiwiYW55Il1dLCJrd3BhcmFtcyI6e319LCJtZXRob2RzIjp7ImZvbyI6eyJwYXJhbXMiOltdLCJrd3BhcmFtcyI6e30sInJlYWRvbmx5Ijp0cnVlLCJyZXQiOiJhbnkifSwia3ciOnsicGFyYW1zIjpbXSwia3dwYXJhbXMiOnsieCI6ImFueSIsInkiOiJhbnkifSwicmVhZG9ubHkiOmZhbHNlLCJyZXQiOiJhbnkiLCJwYXlhYmxlIjpmYWxzZX0sIm1peGVkIjp7InBhcmFtcyI6W1siYSIsImFueSJdLFsiYiIsImFueSJdXSwia3dwYXJhbXMiOnsieCI6ImFueSIsInkiOiJhbnkifSwicmVhZG9ubHkiOmZhbHNlLCJyZXQiOiJhbnkiLCJwYXlhYmxlIjpmYWxzZX0sInBheWFibGUiOnsicGFyYW1zIjpbXSwia3dwYXJhbXMiOnt9LCJyZWFkb25seSI6ZmFsc2UsInJldCI6ImFueSIsInBheWFibGUiOnRydWV9LCJwb3MiOnsicGFyYW1zIjpbWyJ4IiwiYW55Il0sWyJ5IiwiYW55Il1dLCJrd3BhcmFtcyI6e30sInJlYWRvbmx5IjpmYWxzZSwicmV0IjoiYW55IiwicGF5YWJsZSI6ZmFsc2V9fX0ABQU= diff --git a/tests/cases/stable/py/schemas/trivial.0.hash b/tests/cases/stable/py/schemas/trivial.0.hash new file mode 100644 index 000000000..694e62810 --- /dev/null +++ b/tests/cases/stable/py/schemas/trivial.0.hash @@ -0,0 +1 @@ +LRFcZXhpdF9jb2RlIDEAHRWjAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowIhueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALoAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYnoV50UNnwTpw9jS2Fao6ceN+gCB6iwSj9yTzi3zXr1gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDHKEBAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmLCBmb28sIGJhcik6CgkJcGFzcwoKCUBnbC5wdWJsaWMudmlldwoJZGVmIGZvbyhzZWxmKToKCQlwYXNzCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIHBvcyhzZWxmLCB4LCB5KToKCQlwYXNzCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGt3KHNlbGYsICosIHgsIHkpOgoJCXBhc3MKCglAZ2wucHVibGljLndyaXRlCglkZWYgbWl4ZWQoc2VsZiwgYSwgYiwgKiwgeCwgeSk6CgkJcGFzcwoKCUBnbC5wdWJsaWMud3JpdGUucGF5YWJsZQoJZGVmIHBheWFibGUoc2VsZik6CgkJcGFzcwoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/py/schemas/trivial.0_0.hash b/tests/cases/stable/py/schemas/trivial.0_0.hash new file mode 100644 index 000000000..5f76c4b8b --- /dev/null +++ b/tests/cases/stable/py/schemas/trivial.0_0.hash @@ -0,0 +1 @@ +LQHsIXsiY3RvciI6eyJwYXJhbXMiOltbImZvbyIsImFueSJdLFsiYmFyIiwiYW55Il1dLCJrd3BhcmFtcyI6e319LCJtZXRob2RzIjp7ImZvbyI6eyJwYXJhbXMiOltdLCJrd3BhcmFtcyI6e30sInJlYWRvbmx5Ijp0cnVlLCJyZXQiOiJhbnkifSwia3ciOnsicGFyYW1zIjpbXSwia3dwYXJhbXMiOnsieCI6ImFueSIsInkiOiJhbnkifSwicmVhZG9ubHkiOmZhbHNlLCJyZXQiOiJhbnkiLCJwYXlhYmxlIjpmYWxzZX0sIm1peGVkIjp7InBhcmFtcyI6W1siYSIsImFueSJdLFsiYiIsImFueSJdXSwia3dwYXJhbXMiOnsieCI6ImFueSIsInkiOiJhbnkifSwicmVhZG9ubHkiOmZhbHNlLCJyZXQiOiJhbnkiLCJwYXlhYmxlIjpmYWxzZX0sInBheWFibGUiOnsicGFyYW1zIjpbXSwia3dwYXJhbXMiOnt9LCJyZWFkb25seSI6ZmFsc2UsInJldCI6ImFueSIsInBheWFibGUiOnRydWV9LCJwb3MiOnsicGFyYW1zIjpbWyJ4IiwiYW55Il0sWyJ5IiwiYW55Il1dLCJrd3BhcmFtcyI6e30sInJlYWRvbmx5IjpmYWxzZSwicmV0IjoiYW55IiwicGF5YWJsZSI6ZmFsc2V9fX0ABQU= diff --git a/tests/cases/stable/runners/dup-dependency.0.hash b/tests/cases/stable/runners/dup-dependency.0.hash new file mode 100644 index 000000000..1eaec6041 --- /dev/null +++ b/tests/cases/stable/runners/dup-dependency.0.hash @@ -0,0 +1 @@ +LQEAABUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxDfAAAAIyB7CiMgICAiU2VxIjogWwojICAgICB7ICJEZXBlbmRzIjogInNvZnRmbG9hdDp0ZXN0IiB9LAojICAgICB7ICJEZXBlbmRzIjogInNvZnRmbG9hdDp0ZXN0IiB9LAojICAgICB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KIyAgIF0KIyB9CgppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKcHJpbnQoJ0kgYW0gb2snKQpleGl0KDApCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/runners/env-template.0.hash b/tests/cases/stable/runners/env-template.0.hash new file mode 100644 index 000000000..3b158bc69 --- /dev/null +++ b/tests/cases/stable/runners/env-template.0.hash @@ -0,0 +1 @@ +LQEAABUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgw7VAAAAIyB7CiMgICAiU2VxIjogWwojICAgICB7ICJBZGRFbnYiOiB7ICJuYW1lIjogIlgiLCAidmFsIjogIjEiIH0gfSwKIyAgICAgeyAiQWRkRW52IjogeyAibmFtZSI6ICJYIiwgInZhbCI6ICIke1h9OjIiIH0gfSwKIyAgICAgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CiMgICBdCiMgfQoKaW1wb3J0IG9zCgpwcmludChvcy5lbnZpcm9uWydYJ10pCmV4aXQoMCkKAAAAAAAAAAU= diff --git a/tests/cases/stable/runners/malformed_runner.0.hash b/tests/cases/stable/runners/malformed_runner.0.hash new file mode 100644 index 000000000..a286dff53 --- /dev/null +++ b/tests/cases/stable/runners/malformed_runner.0.hash @@ -0,0 +1 @@ +LRGEAWludmFsaWRfY29udHJhY3QAFRWjAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDAhsAAAAjIHsgIkZvbyI6ICJiYXIiIH0KZXhpdCgwKQoABQ== diff --git a/tests/cases/stable/runners/no_runner.0.hash b/tests/cases/stable/runners/no_runner.0.hash new file mode 100644 index 000000000..b5be56f6e --- /dev/null +++ b/tests/cases/stable/runners/no_runner.0.hash @@ -0,0 +1 @@ +LRG0AmludmFsaWRfY29udHJhY3QgYWJzZW50X3J1bm5lcl9jb21tZW50AAUF diff --git a/tests/cases/stable/runners/nondet_custom_runner.0.hash b/tests/cases/stable/runners/nondet_custom_runner.0.hash new file mode 100644 index 000000000..79bb40112 --- /dev/null +++ b/tests/cases/stable/runners/nondet_custom_runner.0.hash @@ -0,0 +1 @@ +LRGMAmludmFsaWRfY29udHJhY3QgbWFsZm9ybWVkX3J1bm5lcgAdFaMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAiG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmAAAAAIMKBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZiehXnRQ2fBOnD2NLYVqjpx436AIHqLBKP3JPOLfNevWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAroAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELAAAAAIM2TQMAACMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnZtIGltcG9ydCByZWdpc3Rlcl9ydW5uZXIsIG1hcF9maWxlCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJZGVmIF9faW5pdF9fKHNlbGYpOgoJCSMgZGV0ZXJtaW5pc3RpYyBjb250ZXh0IHJlZ2lzdGVycyBhIGN1c3RvbSBydW5uZXIKCQljb2RlID0gYicjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfVxubWFya2VyXG4nCgkJcmlkID0gcmVnaXN0ZXJfcnVubmVyKGNvZGUpCgoJCWRlZiBsZWFkZXIoKToKCQkJIyBidXJuIGEgbG9uZyBsb29wIGZpcnN0LCB0aGVuIHRyeSB0byB1c2UgdGhlIGRldC1yZWdpc3RlcmVkIGN1c3RvbQoJCQkjIHJ1bm5lciBmcm9tIGluc2lkZSBub25kZXQuIEN1c3RvbSBydW5uZXJzIHNob3VsZCBiZSBzY29wZWQgdG8gdGhlCgkJCSMgZXhlY3V0aW9uIHRoYXQgcmVnaXN0ZXJlZCB0aGVtLCBzbyB0aGlzIG1hcCBNVVNUIGZhaWwg4oCUIGJ1dCB3aXRoIGEKCQkJIyBzaGFyZWQgcmVnaXN0cnkgaXQgbWF5IGxlYWsuCgkJCWZvciBfIGluIHJhbmdlKDEwKio0KToKCQkJCXBhc3MKCQkJdHJ5OgoJCQkJbWFwX2ZpbGUocmlkLCAnZmlsZScsICcvbWFwcGVkLnR4dCcpCgkJCQlyZXR1cm4gJ25vbmRldCBtYXBwZWQgZGV0LXJlZ2lzdGVyZWQgcnVubmVyIChMRUFLKScKCQkJZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgoJCQkJcmV0dXJuIGYnbm9uZGV0IG1hcCBmYWlsZWQ6IHt0eXBlKGUpLl9fbmFtZV9ffScKCgkJcHJpbnQoZ2wudm0ucnVuX25vbmRldChsZWFkZXIsIGxhbWJkYSByOiBUcnVlKSkKAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/runners/zip/no-zip.0.hash b/tests/cases/stable/runners/zip/no-zip.0.hash new file mode 100644 index 000000000..30b2dd353 --- /dev/null +++ b/tests/cases/stable/runners/zip/no-zip.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgwyrAAAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZik6CgkJcHJpbnQoJ2hlbGxvIHdvcmxkJykKAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/self-run/datetime.0.hash b/tests/cases/stable/self-run/datetime.0.hash new file mode 100644 index 000000000..d5e43b80c --- /dev/null +++ b/tests/cases/stable/self-run/datetime.0.hash @@ -0,0 +1 @@ +LQEAABUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgwheAAAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCmltcG9ydCBkYXRldGltZQoKcHJpbnQoZGF0ZXRpbWUuZGF0ZXRpbWUubm93KCkpCgpleGl0KDApCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/self-run/floats.0.hash b/tests/cases/stable/self-run/floats.0.hash new file mode 100644 index 000000000..d14ee96da --- /dev/null +++ b/tests/cases/stable/self-run/floats.0.hash @@ -0,0 +1 @@ +LQEAABUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgzZBAwAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IG1hdGgKCmltcG9ydCBvcGVyYXRvcgoKZGF0YTogbGlzdFtmbG9hdF0gPSBbCgltYXRoLm5hbiwKCW1hdGguaW5mLAoJLW1hdGguaW5mLAoJMS40MTQyMTM1NjIzNywKCS0xLjQxNDIxMzU2MjM3LAoJMS4wLAoJLTEsCgkxZTUsCgktMWU1LAoJMC4wLAoJLTAuMCwKXQoKaW1wb3J0IHN0cnVjdAppbXBvcnQgbnVtcHkgYXMgbnAKCmZvciB4IGluIGRhdGE6CglwcmludCgnbmV3IHgnKQoJZm9yIHkgaW4gZGF0YToKCQlmb3Igb3AgaW4gW21hdGguZmxvb3IsIG1hdGguY2VpbCwgbWF0aC5zcXJ0LCBtYXRoLnNpbiwgaW50LCBtYXRoLmV4cF06CgkJCXRyeToKCQkJCXJlcyA9IG9wKHgpCgkJCQlpZiBtYXRoLmlzbmFuKHJlcyk6CgkJCQkJcmVzID0gbWF0aC5uYW4KCQkJCXMgPSBzdHJ1Y3QucGFjaygnPmQnLCByZXMpCgkJCQlwcmludChmJ1x0e3g6LjVmfSB7b3B9IHtyZXM6LjVmfSB7cy5oZXgoKX0nKQoJCQlleGNlcHQ6CgkJCQlwYXNzCgkJcHJpbnQoJ1x0bmV3IHknKQoJCWZvciBvcCBpbiBbCgkJCW9wZXJhdG9yLmFkZCwKCQkJb3BlcmF0b3Iuc3ViLAoJCQlvcGVyYXRvci5tdWwsCgkJCW9wZXJhdG9yLnRydWVkaXYsCgkJXTogICMgb3BlcmF0b3IucG93CgkJCXRyeToKCQkJCXJlcyA9IG9wKHgsIHkpCgkJCQlpZiBtYXRoLmlzbmFuKHJlcyk6CgkJCQkJcmVzID0gbWF0aC5uYW4KCQkJCXMgPSBzdHJ1Y3QucGFjaygnPmQnLCByZXMpCgkJCQlwcmludChmJ1x0XHR7eDouNWZ9IHtvcH0ge3k6LjVmfSB7cmVzOi41Zn0ge3MuaGV4KCl9JykKCQkJZXhjZXB0OgoJCQkJcGFzcwoKZXhpdCgwKQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/self-run/formats.0.hash b/tests/cases/stable/self-run/formats.0.hash new file mode 100644 index 000000000..1e7481d7d --- /dev/null +++ b/tests/cases/stable/self-run/formats.0.hash @@ -0,0 +1 @@ +LQEAABUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyQdAgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCmZyb20gZ2VubGF5ZXIuc3RvcmFnZS5faW50ZXJuYWwuZ2VuZXJhdGUgaW1wb3J0IGdlbmVyYXRlX3N0b3JhZ2UKaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0IEFkZHJlc3MKCgpAZ2VuZXJhdGVfc3RvcmFnZQpjbGFzcyBUZXN0OgoJYXJyOiBnbC5EeW5BcnJheVtzdHJdCgltYXA6IGdsLlRyZWVNYXBbc3RyLCBOb25lXQoKCmFkZHIgPSBBZGRyZXNzKGInXHhhMicgKiAyMCkKcHJpbnQoYWRkcikKcHJpbnQoZid7YWRkcn0nKQpwcmludChmJ3thZGRyIXJ9JykKcHJpbnQoZid7YWRkciFzfScpCnByaW50KGYne2FkZHI6Y2R9JykKcHJpbnQoZid7YWRkcjpiNjR9JykKcHJpbnQoZid7YWRkcjp4fScpCnByaW50KGYne2FkZHI6fScpCgp0ID0gVGVzdCgpCnQuYXJyLmV4dGVuZChbJzEnLCAnMicsICczJ10pCnQubWFwLnVwZGF0ZSh7JzEnOiBOb25lLCAnNCc6IE5vbmV9KQpwcmludChmJ3t0LmFycn0nKQpwcmludChmJ3t0Lm1hcH0nKQpleGl0KDApCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/self-run/issue_163.0.hash b/tests/cases/stable/self-run/issue_163.0.hash new file mode 100644 index 000000000..d4a79330a --- /dev/null +++ b/tests/cases/stable/self-run/issue_163.0.hash @@ -0,0 +1 @@ +LQEAABUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxQoAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCmZyb20gZ2VubGF5ZXIuc3RvcmFnZS5faW50ZXJuYWwuZ2VuZXJhdGUgaW1wb3J0IGdlbmVyYXRlX3N0b3JhZ2UKCgpAZ2VuZXJhdGVfc3RvcmFnZQpjbGFzcyBQcjoKCXg6IGdsLlRyZWVNYXBbc3RyLCBzdHJdCgoKYSA9IFByKCkKCnRyeToKCWEueCA9IHsneCc6ICd5J30KZXhjZXB0IEFzc2VydGlvbkVycm9yIGFzIGU6CglwcmludCgqZS5hcmdzKQoKZXhpdCgwKQoAAAAAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/self-run/module/np.0.hash b/tests/cases/stable/self-run/module/np.0.hash new file mode 100644 index 000000000..666bae33b --- /dev/null +++ b/tests/cases/stable/self-run/module/np.0.hash @@ -0,0 +1 @@ +LQEAABUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgwhrAAAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IG51bXB5IGFzIG5wCgpwcmludChucC5hcnJheShbMSwgMiwgM10sIGR0eXBlPWludCkgKiogMikKZXhpdCgwKQoAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/self-run/module/pil.0.hash b/tests/cases/stable/self-run/module/pil.0.hash new file mode 100644 index 000000000..ad0d3e255 --- /dev/null +++ b/tests/cases/stable/self-run/module/pil.0.hash @@ -0,0 +1 @@ +LQEAABUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgzD5AgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KZnJvbSBQSUwgaW1wb3J0IEltYWdlCgppbXBvcnQgaW8KCmltX2RhdGEgPSBiJ1x4ODlQTkdcclxuXHgxYVxuXHgwMFx4MDBceDAwXHJJSERSXHgwMFx4MDBceDAwJFx4MDBceDAwXHgwMFx4MTVceDAxXHgwM1x4MDBceDAwXHgwMFx4MTRceGU4XHhkZVx4ZDNceDAwXHgwMFx4MDBceDA2UExURVx4ZmZceGZmXHhmZlx4MDBceDAwXHgwMFVceGMyXHhkM35ceDAwXHgwMFx4MDBUSURBVHhceDljY2BAXHgwMlx4MGVceDBjXHgwY1x4MWNceDBjXHgwY1x4MWVceGNjXHgwZnhceDgwXHhhNFx4YTNceDAyXHg5MFx4OGNceDAwXHg5M1x4MDFQMlx4ODFceDhiXHg4MVx4YTFceGMwXHhmMVx4ODBceDEwXHgwM0NceDgyY1x4ODNceDEwXHg4OFx4ZWQgXHgwNFx4MTZceDA3XHg5MVx4OGFceDAyXHgxMFx4ZDJceDA4RHJceGQ4XHgwMU1QXHhlNFFceDAyXHg5MlxuLEogY1x4OTlceDE0XHgxOFx4MTh4XHhjMFx4YjZceGIwICxceDA0XHgwMFx4ODRceGFiXHgwY1x4Y2FceDAyXHg4ZSpceGIwXHgwMFx4MDBceDAwXHgwMElFTkRceGFlQmBceDgyJwoKaW1nID0gSW1hZ2Uub3Blbihpby5CeXRlc0lPKGltX2RhdGEpKQppZiBpbWcubW9kZSAhPSAnUkdCJzoKCWltZyA9IGltZy5jb252ZXJ0KCdSR0InKQoKcGl4ZWxzID0gbGlzdChpbWcuZ2V0ZGF0YSgpKQoKcmVzID0gc2V0KCkKCmZvciBpIGluIHBpeGVsczoKCXJlcy5hZGQoaSkKCnByaW50KGxpc3Qoc29ydGVkKHJlcykpKQoKZXhpdCgwKQoAAAAF diff --git a/tests/cases/stable/self-run/re.0.hash b/tests/cases/stable/self-run/re.0.hash new file mode 100644 index 000000000..e70341d58 --- /dev/null +++ b/tests/cases/stable/self-run/re.0.hash @@ -0,0 +1 @@ +LQEAABUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyQsAgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCmltcG9ydCByZQoKYXNzZXJ0IHJlLm1hdGNoKCcoYWJ8YmEpJywgJ2FiJykuc3BhbigpID09ICgwLCAyKQphc3NlcnQgcmUubWF0Y2goJyhhYnxiYSknLCAnYmEnKS5zcGFuKCkgPT0gKDAsIDIpCmFzc2VydCByZS5tYXRjaCgnKGFiY3xiYWN8Y2F8Y2IpJywgJ2FiYycpLnNwYW4oKSA9PSAoMCwgMykKYXNzZXJ0IHJlLm1hdGNoKCcoYWJjfGJhY3xjYXxjYiknLCAnYmFjJykuc3BhbigpID09ICgwLCAzKQphc3NlcnQgcmUubWF0Y2goJyhhYmN8YmFjfGNhfGNiKScsICdjYScpLnNwYW4oKSA9PSAoMCwgMikKYXNzZXJ0IHJlLm1hdGNoKCcoYWJjfGJhY3xjYXxjYiknLCAnY2InKS5zcGFuKCkgPT0gKDAsIDIpCmFzc2VydCByZS5tYXRjaCgnKChhKXwoYil8KGMpKScsICdhJykuc3BhbigpID09ICgwLCAxKQphc3NlcnQgcmUubWF0Y2goJygoYSl8KGIpfChjKSknLCAnYicpLnNwYW4oKSA9PSAoMCwgMSkKYXNzZXJ0IHJlLm1hdGNoKCcoKGEpfChiKXwoYykpJywgJ2MnKS5zcGFuKCkgPT0gKDAsIDEpCgpleGl0KDApCgAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/self-run/typing_is_ok.0.hash b/tests/cases/stable/self-run/typing_is_ok.0.hash new file mode 100644 index 000000000..c221ee8ff --- /dev/null +++ b/tests/cases/stable/self-run/typing_is_ok.0.hash @@ -0,0 +1 @@ +LQEAABUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyqZAgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCiMgZnJvbSBfX2Z1dHVyZV9fIGltcG9ydCBhbm5vdGF0aW9ucwoKaW1wb3J0IHR5cGluZwppbXBvcnQgdHlwZXMKCgpjbGFzcyBGb29bWF06CglhOiBYCgoKZGVmIHRzdCh4KToKCXByaW50KGYnPT09IHt4Ll9fbmFtZV9ffScpCglwcmludCh0eXBlKHgpKQoJcHJpbnQoeCkKCWlmIGlzaW5zdGFuY2UoeCwgdHlwZXMuR2VuZXJpY0FsaWFzKToKCQlwcmludChmJ29yaWdpbj17eC5fX29yaWdpbl9ffScpCgkJcHJpbnQoZidhcmdzPXt4Ll9fYXJnc19ffScpCgllbGlmIGlzaW5zdGFuY2UoeCwgdHlwaW5nLl9HZW5lcmljQWxpYXMpOiAgIyB0eXBlOiBpZ25vcmUKCQlwcmludChmJ29yaWdpbj17eC5fX29yaWdpbl9ffScpCgkJcHJpbnQoZidhcmdzPXt4Ll9fYXJnc19ffScpCglpZiBub3QgaXNpbnN0YW5jZSh4LCB0eXBlcy5HZW5lcmljQWxpYXMpOgoJCWZvciBrLCB2IGluIHR5cGluZy5nZXRfdHlwZV9oaW50cyh4KS5pdGVtcygpOgoJCQlpZiBpc2luc3RhbmNlKHYsIHR5cGluZy5UeXBlVmFyKToKCQkJCXYgPSB2Ll9fbmFtZV9fCgkJCXByaW50KGYnXHR7a306IHt2fScpCgoKdHN0KEZvbykKCnRzdChsaXN0W3N0cl0pCgoKY2xhc3MgVGVzdDoKCWZvbzogRm9vW3N0cl0KCgp0c3QoVGVzdCkKZXhpdCgwKQoAAAAF diff --git a/tests/cases/stable/storage/alloc_generic.0.hash b/tests/cases/stable/storage/alloc_generic.0.hash new file mode 100644 index 000000000..874d5188c --- /dev/null +++ b/tests/cases/stable/storage/alloc_generic.0.hash @@ -0,0 +1 @@ +LQEAABUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxIQAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCmZyb20gZ2VubGF5ZXIuc3RvcmFnZSBpbXBvcnQgYWxsb3cKZnJvbSBkYXRhY2xhc3NlcyBpbXBvcnQgZGF0YWNsYXNzCgoKQGFsbG93CkBkYXRhY2xhc3MKY2xhc3MgVGVzdFtUXToKCWZvbzogVAoKCnRzdCA9IGdsLnN0b3JhZ2UuaW5tZW1fYWxsb2NhdGUoVGVzdFtzdHJdLCAnMTIzJykKcHJpbnQodHN0KQoKZXhpdCgwKQoAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/storage/alloc_generic_err.0.hash b/tests/cases/stable/storage/alloc_generic_err.0.hash new file mode 100644 index 000000000..a29979154 --- /dev/null +++ b/tests/cases/stable/storage/alloc_generic_err.0.hash @@ -0,0 +1 @@ +LQEAABUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxyoAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCmZyb20gZ2VubGF5ZXIuc3RvcmFnZSBpbXBvcnQgYWxsb3cKZnJvbSBkYXRhY2xhc3NlcyBpbXBvcnQgZGF0YWNsYXNzCmZyb20gZ2VubGF5ZXIuc3RvcmFnZS5faW50ZXJuYWwuZ2VuZXJhdGUgaW1wb3J0IGdlbmVyYXRlX3N0b3JhZ2UKCgpAYWxsb3cKQGRhdGFjbGFzcwpjbGFzcyBUZXN0W1RdOgoJZm9vOiBUCgoKQGdlbmVyYXRlX3N0b3JhZ2UKY2xhc3MgQmFyOgoJdDogVGVzdFtzdHJdCgoKdHJ5OgoJdHN0ID0gVGVzdCgnMTIzJykKCXByaW50KHRzdCkKZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgoJcHJpbnQoZSkKCWZvciBuIGluIGUuX19ub3Rlc19fOgoJCXByaW50KG4pCgpleGl0KDApCgAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/storage/base.0.hash b/tests/cases/stable/storage/base.0.hash new file mode 100644 index 000000000..17b366cc0 --- /dev/null +++ b/tests/cases/stable/storage/base.0.hash @@ -0,0 +1 @@ +LQEAABUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyZYAgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCmZyb20gZ2VubGF5ZXIuc3RvcmFnZSBpbXBvcnQgYWxsb3cKZnJvbSBnZW5sYXllci5zdG9yYWdlLl9pbnRlcm5hbC5nZW5lcmF0ZSBpbXBvcnQgZ2VuZXJhdGVfc3RvcmFnZQoKCkBhbGxvdwpjbGFzcyBUZXN0OgoJZm9vOiBpNjQKCWJhcjogaTY0CglzdDogc3RyCgoJZGVmIGFiYyhzZWxmKToKCQlyZXR1cm4gc2VsZi5mb28KCgpAZ2VuZXJhdGVfc3RvcmFnZQpjbGFzcyBDb21wb3NpdGU6CglhOiBUZXN0CgliOiBUZXN0CgoKdHN0ID0gQ29tcG9zaXRlKCkKCnN0b3JfbWFuID0gdHN0Ll9zdG9yYWdlX3Nsb3QubWFuYWdlciAgIyB0eXBlOiBpZ25vcmUKCnRzdC5hLmZvbyA9IDY1NTM1CnRzdC5hLmJhciA9IDIqKjMyCnRzdC5hLnN0ID0gJzEyMycKdHN0LmIuZm9vID0gMTMKdHN0LmIuc3QgPSAnMzIxJwoKc3Rvcl9tYW4uZGVidWcoKQpwcmludCh0c3QuYS5zdCwgdHN0LmIuc3QpCgp0c3QuYSA9IHRzdC5iCgpzdG9yX21hbi5kZWJ1ZygpCnByaW50KHRzdC5hLnN0LCB0c3QuYi5zdCkKCmV4aXQoMCkKAAAAAAU= diff --git a/tests/cases/stable/storage/bootstrapper.0.hash b/tests/cases/stable/storage/bootstrapper.0.hash new file mode 100644 index 000000000..13146592d --- /dev/null +++ b/tests/cases/stable/storage/bootstrapper.0.hash @@ -0,0 +1 @@ +LQEAACUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAg+AB4w0AACMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CgppbXBvcnQgdHlwaW5nCgppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKCl9DQUxDX01BTkFHRVIgPSBnbC5zdG9yYWdlLklubWVtTWFuYWdlcigpCkNPREVfU0xPVCA9ICgKCV9DQUxDX01BTkFHRVIuZ2V0X3N0b3JlX3Nsb3QoZ2wuc3RvcmFnZS5ST09UX1NMT1RfSUQpCgkuaW5kaXJlY3QoZ2wudm0uQUJJLnJvb3Rfb2Zmc2V0cy5DT0RFKQoJLmlkCikKTE9DS0VEX1NMT1QgPSAoCglfQ0FMQ19NQU5BR0VSLmdldF9zdG9yZV9zbG90KGdsLnN0b3JhZ2UuUk9PVF9TTE9UX0lEKQoJLmluZGlyZWN0KGdsLnZtLkFCSS5yb290X29mZnNldHMuTE9DS0VEX1NMT1RTKQoJLmlkCikKClZBQ0FOVF9TTE9UID0gX0NBTENfTUFOQUdFUi5nZXRfc3RvcmVfc2xvdChnbC5zdG9yYWdlLlJPT1RfU0xPVF9JRCkuaW5kaXJlY3QoCglnbC52bS5BQkkucm9vdF9vZmZzZXRzLk1BSk9SCikKClNQRUNJQUxfU0xPVFMgPSBbZ2wuc3RvcmFnZS5ST09UX1NMT1RfSUQsIENPREVfU0xPVCwgTE9DS0VEX1NMT1RdCgpTUEVDSUFMX1NMT1RTX1RXSU5TID0gewoJc2x0OiBWQUNBTlRfU0xPVC5pbmRpcmVjdChpKS5pZCBmb3IgaSwgc2x0IGluIGVudW1lcmF0ZShTUEVDSUFMX1NMT1RTKQp9CgoKZGVmIGdldF90d2luX3ZsYShzbG90X2lkOiBieXRlcykgLT4gZ2wuc3RvcmFnZS5WTEFbZ2wudHlwZXMudThdOgoJcmV0dXJuIGdsLnN0b3JhZ2UuY2FzdF9zbG90KAoJCWdsLnN0b3JhZ2UuVkxBW2dsLnR5cGVzLnU4XSwgZ2wuc3RvcmFnZS5Sb290Lk1BTkFHRVIsIHNsb3RfaWQsIDAKCSkKCgpkZWYgd3JpdGVfdG9fdHdpbihzbG90X2lkOiBieXRlcywgb2Zmc2V0OiBpbnQsIGRhdGE6IGJ5dGVzKToKCWFzX3ZsYSA9IGdldF90d2luX3ZsYShzbG90X2lkKQoJb2xkX2xlbiA9IGxlbihhc192bGEpCglhc192bGEuc2xvdCgpLndyaXRlKGFzX3ZsYS5kYXRhX29mZnNldCgpICsgb2Zmc2V0LCBkYXRhKQoJYXNfdmxhLnNldF9sZW5ndGgobWF4KG9sZF9sZW4sIG9mZnNldCArIGxlbihkYXRhKSkpCgoKZGVmIHJlYWRfZnJvbV90d2luKHNsb3RfaWQ6IGJ5dGVzLCBvZmZzZXQ6IGludCwgbGVuZ3RoOiBpbnQpIC0+IGJ5dGVzOgoJc2xvdCA9IGdsLnN0b3JhZ2UuUm9vdC5NQU5BR0VSLmdldF9zdG9yZV9zbG90KHNsb3RfaWQpCglyZXR1cm4gc2xvdC5yZWFkKG9mZnNldCArIDQsIGxlbmd0aCkKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZiwgKiwgc2F2ZV9kZWZhdWx0X2xvY2tlZF9zbG90czogYm9vbCA9IFRydWUpOgoJCXJvb3QgPSBnbC5zdG9yYWdlLlJvb3QuZ2V0KCkKCgkJaWYgc2F2ZV9kZWZhdWx0X2xvY2tlZF9zbG90czoKCQkJdHdpbl9zbG90X2lkID0gU1BFQ0lBTF9TTE9UU19UV0lOU1tMT0NLRURfU0xPVF0KCQkJbG9ja2VkX3Nsb3RzX2RzdCA9IGdsLnN0b3JhZ2UuY2FzdF9zbG90KAoJCQkJZ2wuc3RvcmFnZS5WTEFbZ2wudHlwZXMudTI1Nl0sIGdsLnN0b3JhZ2UuUm9vdC5NQU5BR0VSLCB0d2luX3Nsb3RfaWQsIDQKCQkJKQoJCQlsb2NrZWRfc2xvdHNfZHN0LmFzc2lnbihyb290LmxvY2tlZF9zbG90cy5nZXQoKSkKCgkJCWxvY2tlZF9zbG90c19kc3RfdmxhID0gZ2V0X3R3aW5fdmxhKHR3aW5fc2xvdF9pZCkKCQkJbG9ja2VkX3Nsb3RzX2RzdF92bGEuc2V0X2xlbmd0aCgKCQkJCWxlbihsb2NrZWRfc2xvdHNfZHN0KSAqIDMyICsgbG9ja2VkX3Nsb3RzX2RzdC5kYXRhX29mZnNldCgpCgkJCSkKCgkJcm9vdC5sb2NrZWRfc2xvdHMuZ2V0KCkudHJ1bmNhdGUoKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiB3cml0ZShzZWxmLCBkYXRhOiBsaXN0W3R5cGluZy5BbnldKToKCQkiIiIKCQlXcml0ZSBkYXRhIHRvIHRoZSBjb250cmFjdC4KCgkJOnBhcmFtIGRhdGE6IGxpc3Qgb2YgZGF0YSBpdGVtcyB0byB3cml0ZSBpbiBmb3JtYXQgYGAoc2xvdDogYnl0ZVszMl0sIG9mZnNldDogdTMyLCBkYXRhOiBieXRlcylgYAoJCSIiIgoKCQlmb3Igc2xvdCwgb2Zmc2V0LCBzbGljZSBpbiBkYXRhOgoJCQlpZiBzbG90IGluIFNQRUNJQUxfU0xPVFNfVFdJTlMudmFsdWVzKCk6CgkJCQlnbC52bS5Vc2VyRXJyb3IuaW1tZWRpYXRlKCdDYW5ub3Qgd3JpdGUgdG8gdGhlIHRlbXBvcmFyeSBjb2RlIHNsb3RzJykKCQkJaWYgdHdpbiA6PSBTUEVDSUFMX1NMT1RTX1RXSU5TLmdldChzbG90KToKCQkJCXdyaXRlX3RvX3R3aW4odHdpbiwgb2Zmc2V0LCBzbGljZSkKCQkJZWxzZToKCQkJCWdsLnN0b3JhZ2UuUm9vdC5NQU5BR0VSLmdldF9zdG9yZV9zbG90KHNsb3QpLndyaXRlKG9mZnNldCwgc2xpY2UpCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIHB1c2hfY29kZShzZWxmLCBjb2RlOiBieXRlcyk6CgkJIiIiCgkJUHVzaCBjb2RlIHRvIHRoZSBjb250cmFjdC4gVGhpcyB3aWxsIHdyaXRlIHRoZSBjb2RlIHRvIGEgdGVtcG9yYXJ5IHNsb3QsIHdoaWNoIGNhbiBiZSBjb3BpZWQgdG8gdGhlIGNvZGUgc2xvdCBpbiB0aGUgYGBmaW5pc2hgYCBtZXRob2QuCgoJCTpwYXJhbSBjb2RlOiBjb2RlIHRvIHB1c2gKCgkJLi4gd2FybmluZzo6CgkJCUV4YWN0bHkgb25lIG9mIGBgd3JpdGVgYCBvciBgYHB1c2hfY29kZWBgIG11c3QgYmUgY2FsbGVkIGZvciBjb2RlIGluaXRpYWxpemF0aW9uLAoJCQlvdGhlcndpc2UgdGhlIGNvbnRyYWN0IG1heSBiZSBsZWZ0IGluIHVuZGVmaW5lZCBzdGF0ZQoJCSIiIgoKCQl0d2luX3Nsb3RfaWQgPSBTUEVDSUFMX1NMT1RTX1RXSU5TW0NPREVfU0xPVF0KCQljb2RlX3R3aW5fdmxhID0gZ2V0X3R3aW5fdmxhKHR3aW5fc2xvdF9pZCkKCQljb2RlX3ZsYSA9IGdsLnN0b3JhZ2UuY2FzdF9zbG90KAoJCQlnbC5zdG9yYWdlLlZMQVtnbC50eXBlcy51OF0sIGdsLnN0b3JhZ2UuUm9vdC5NQU5BR0VSLCB0d2luX3Nsb3RfaWQsIDQKCQkpCgkJY29kZV92bGEuZXh0ZW5kKGNvZGUpCgkJbmV3X2xlbiA9IGxlbihjb2RlX3ZsYSkKCQljb2RlX3R3aW5fdmxhLnNldF9sZW5ndGgobmV3X2xlbiArIDQpCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGZpbmlzaChzZWxmKToKCQkiIiIKCQlGaW5pc2ggYm9vdHN0cmFwcGluZy4gVGhpcyB3aWxsIGNvcHkgdGhlIGNvZGUgZnJvbSB0aGUgdGVtcG9yYXJ5IHNsb3QgdG8gdGhlIGNvZGUgc2xvdCBhbmQgbWFrZSBpdCBhdmFpbGFibGUgZm9yIGV4ZWN1dGlvbi4KCQkiIiIKCQlCVUZfU0laRSA9IDY1NTM2CgkJZm9yIGRzdCwgc3JjIGluIFNQRUNJQUxfU0xPVFNfVFdJTlMuaXRlbXMoKToKCQkJdmxhX2Zyb20gPSBnZXRfdHdpbl92bGEoc3JjKQoJCQljb3B5X2xlbiA9IGxlbih2bGFfZnJvbSkKCQkJdG8gPSBnbC5zdG9yYWdlLlJvb3QuTUFOQUdFUi5nZXRfc3RvcmVfc2xvdChkc3QpCgkJCWZvciBvZmZzZXQgaW4gcmFuZ2UoMCwgY29weV9sZW4sIEJVRl9TSVpFKToKCQkJCWNodW5rX3NpemUgPSBtaW4oQlVGX1NJWkUsIGNvcHlfbGVuIC0gb2Zmc2V0KQoJCQkJZGF0YSA9IHZsYV9mcm9tLnNsb3QoKS5yZWFkKHZsYV9mcm9tLmRhdGFfb2Zmc2V0KCkgKyBvZmZzZXQsIGNodW5rX3NpemUpCgkJCQl0by53cml0ZShvZmZzZXQsIGRhdGEpCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLUAhgMv1tlUOkSeUwufY18+ny40k+mX7nSFAcpg/v3UAAAAACDCogAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/storage/bootstrapper.0_0.hash b/tests/cases/stable/storage/bootstrapper.0_0.hash new file mode 100644 index 000000000..379cebca7 --- /dev/null +++ b/tests/cases/stable/storage/bootstrapper.0_0.hash @@ -0,0 +1 @@ +LQEAAA0VowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDAioAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/storage/bootstrapper.0_0_0.hash b/tests/cases/stable/storage/bootstrapper.0_0_0.hash new file mode 100644 index 000000000..06869af21 --- /dev/null +++ b/tests/cases/stable/storage/bootstrapper.0_0_0.hash @@ -0,0 +1 @@ +LQEAAA0VowLGyCM48EiqiMEdOP35uFBCQ1ppRLdLR6+O1DknMJVe2QAAAACDCGsAAABnAAAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCgoKY2xhc3MgQ29udHJhYwAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/storage/bootstrapper.0_0_0_0.hash b/tests/cases/stable/storage/bootstrapper.0_0_0_0.hash new file mode 100644 index 000000000..29aae7d93 --- /dev/null +++ b/tests/cases/stable/storage/bootstrapper.0_0_0_0.hash @@ -0,0 +1 @@ +LQEAABUVowLGyCM48EiqiMEdOP35uFBCQ1ppRLdLR6+O1DknMJVe2QAAAACDAtIAAADOAAAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxhFaMCxsgjOPBIqojBHTj9+bhQQkNaaUS3S0evjtQ5JzCVXtkAAAADgwgKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWZpZWxkOiBpMzIKCglAZ2wucHVibGljLndyaXRlCglkZWYgZ2V0X2ZpZWxkKHNlbGYpOgoJCXByaW50KGludChzZWxmLmZpZWxkKSkKAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/storage/bootstrapper.0_0_0_0_0.hash b/tests/cases/stable/storage/bootstrapper.0_0_0_0_0.hash new file mode 100644 index 000000000..da2ca18fc --- /dev/null +++ b/tests/cases/stable/storage/bootstrapper.0_0_0_0_0.hash @@ -0,0 +1 @@ +LQEAABUVowIhueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZgAAAACDCgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALoAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYnoV50UNnwTpw9jS2Fao6ceN+gCB6iwSj9yTzi3zXr1gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDDs4AAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglmaWVsZDogaTMyCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIGdldF9maWVsZChzZWxmKToKCQlwcmludChpbnQoc2VsZi5maWVsZCkpCi5yb290X29mZnNldHMuBQ== diff --git a/tests/cases/stable/storage/bootstrapper.0_0_0_0_0_0.hash b/tests/cases/stable/storage/bootstrapper.0_0_0_0_0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/storage/bootstrapper.0_0_0_0_0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/storage/floats.0.hash b/tests/cases/stable/storage/floats.0.hash new file mode 100644 index 000000000..52ac99599 --- /dev/null +++ b/tests/cases/stable/storage/floats.0.hash @@ -0,0 +1 @@ +LQEAABUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxZSAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCmZyb20gZ2VubGF5ZXIuc3RvcmFnZS5faW50ZXJuYWwuZ2VuZXJhdGUgaW1wb3J0IGdlbmVyYXRlX3N0b3JhZ2UKCgpAZ2VuZXJhdGVfc3RvcmFnZQpjbGFzcyBUZXN0OgoJZm9vOiBmbG9hdAoKCWRlZiBhYmMoc2VsZik6CgkJcmV0dXJuIHNlbGYuZm9vCgoKdHN0ID0gVGVzdCgpCnRzdC5mb28gPSAwLjUKCmFzc2VydCB0c3QuZm9vID09IDAuNQphc3NlcnQgdHlwZSh0c3QuZm9vKSBpcyBmbG9hdApwcmludCh0c3QuZm9vKQoKZXhpdCgwKQoAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/storage/gvm-89.0.hash b/tests/cases/stable/storage/gvm-89.0.hash new file mode 100644 index 000000000..63edebba9 --- /dev/null +++ b/tests/cases/stable/storage/gvm-89.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxhpAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCmZyb20gZGF0YWNsYXNzZXMgaW1wb3J0IGRhdGFjbGFzcwppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgpmcm9tIGdlbmxheWVyLnN0b3JhZ2UgaW1wb3J0IGFsbG93CgoKQGFsbG93CkBkYXRhY2xhc3MKY2xhc3MgRm9vOgoJeDogZ2wuRHluQXJyYXlbc3RyXQoKCmNsYXNzIE1haW4oZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJZjogZ2wuRHluQXJyYXlbRm9vXQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYpOgoJCXNlbGYuZi5hcHBlbmQoRm9vKFsnMTIzJ10pKQoJCXJldHVybiBbaSBmb3IgaSBpbiBzZWxmLmZdCgAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/storage/gvm-89.0_0.hash b/tests/cases/stable/storage/gvm-89.0_0.hash new file mode 100644 index 000000000..c834387f1 --- /dev/null +++ b/tests/cases/stable/storage/gvm-89.0_0.hash @@ -0,0 +1 @@ +LQENDgF4DRwxMjMAJRWjAkarTtJntGExRjClCClTeapPszpBSCLunXLw6y4spm7AAAAAAIMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLXx9ztv0A3R7xFE8sm8nft+EExO+bPdwDogzFYlc/vDAAAAACDAjEyMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMC4a4jQSeS32tqmPt8mDlwH7iwK2/H7QIoEPeDRklGhecAAAAAgwIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAvC/CNTNsNC9yOvuCNfiE8+cb20NpEyVEFeSNxzeGgcsAAAAAIMCAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/storage/locking/default-frozen.0.hash b/tests/cases/stable/storage/locking/default-frozen.0.hash new file mode 100644 index 000000000..c2264948c --- /dev/null +++ b/tests/cases/stable/storage/locking/default-frozen.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgzhxAwAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCgpuZXdfY29kZSA9IGIiIiJcCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CnByaW50KCJQYXRjaGVkISIpCmV4aXQoMzApCiIiIgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmLCBtb2RpZmllcnM6IGxpc3RbQWRkcmVzc10sIG1vZGlmeV9pbl9jdG9yOiBib29sKToKCQlyb290ID0gZ2wuc3RvcmFnZS5Sb290LmdldCgpCgkJcm9vdC51cGdyYWRlcnMuZ2V0KCkuZXh0ZW5kKG1vZGlmaWVycykKCgkJc2VsZi5zaG93X2luZm8oKQoKCQlpZiBtb2RpZnlfaW5fY3RvcjoKCQkJc2VsZi50cnlfbW9kaWZ5KCkKCglkZWYgc2hvd19pbmZvKHNlbGYpOgoJCXJvb3QgPSBnbC5zdG9yYWdlLlJvb3QuZ2V0KCkKCgkJcHJpbnQobGlzdChyb290LmxvY2tlZF9zbG90cy5nZXQoKSkpCgkJcHJpbnQobGlzdChyb290LnVwZ3JhZGVycy5nZXQoKSkpCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG5vcChzZWxmKToKCQlwYXNzCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIHRyeV9tb2RpZnkoc2VsZik6CgkJcm9vdCA9IGdsLnN0b3JhZ2UuUm9vdC5nZXQoKQoKCQlzZWxmLnNob3dfaW5mbygpCgoJCWNvZGUgPSByb290LmNvZGUuZ2V0KCkKCQl0cnk6CgkJCWNvZGUudHJ1bmNhdGUoKSAgIyA8LSB3ZSBzaG91bGQgZW5jb3VudGVyIGVycm9yIGhlcmUKCQlleGNlcHQgQmFzZUV4Y2VwdGlvbiBhcyBlOgoJCQlwcmludChlKQoJCWVsc2U6CgkJCWNvZGUuYXNzaWduKG5ld19jb2RlKQoJCXByaW50KGxlbihjb2RlKSA9PSBsZW4obmV3X2NvZGUpKQoAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/storage/locking/default-frozen.0_0.hash b/tests/cases/stable/storage/locking/default-frozen.0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/storage/locking/default-frozen.0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/storage/locking/default-frozen.0_0_0.hash b/tests/cases/stable/storage/locking/default-frozen.0_0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/storage/locking/default-frozen.0_0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/storage/locking/modify_ctor.0.hash b/tests/cases/stable/storage/locking/modify_ctor.0.hash new file mode 100644 index 000000000..62e3f12b8 --- /dev/null +++ b/tests/cases/stable/storage/locking/modify_ctor.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgzg/AAAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KcHJpbnQoIlBhdGNoZWQhIikKZXhpdCgzMCkKIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCgpuZXdfY29kZSA9IGIiIiJcCiMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CnByaW50KCJQYXRjaGVkISIpCmV4aXQoMzApCiIiIgoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmLCBtb2RpZmllcnM6IGxpc3RbQWRkcmVzc10sIG1vZGlmeV9pbl9jdG9yOiBib29sKToKCQlyb290ID0gZ2wuc3RvcmFnZS5Sb290LmdldCgpCgkJcm9vdC51cGdyYWRlcnMuZ2V0KCkuZXh0ZW5kKG1vZGlmaWVycykKCgkJc2VsZi5zaG93X2luZm8oKQoKCQlpZiBtb2RpZnlfaW5fY3RvcjoKCQkJc2VsZi50cnlfbW9kaWZ5KCkKCglkZWYgc2hvd19pbmZvKHNlbGYpOgoJCXJvb3QgPSBnbC5zdG9yYWdlLlJvb3QuZ2V0KCkKCgkJcHJpbnQobGlzdChyb290LmxvY2tlZF9zbG90cy5nZXQoKSkpCgkJcHJpbnQobGlzdChyb290LnVwZ3JhZGVycy5nZXQoKSkpCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG5vcChzZWxmKToKCQlwYXNzCgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIHRyeV9tb2RpZnkoc2VsZik6CgkJcm9vdCA9IGdsLnN0b3JhZ2UuUm9vdC5nZXQoKQoKCQlzZWxmLnNob3dfaW5mbygpCgoJCWNvZGUgPSByb290LmNvZGUuZ2V0KCkKCQl0cnk6CgkJCWNvZGUudHJ1bmNhdGUoKSAgIyA8LSB3ZSBzaG91bGQgZW5jb3VudGVyIGVycm9yIGhlcmUKCQlleGNlcHQgQmFzZUV4Y2VwdGlvbiBhcyBlOgoJCQlwcmludChlKQoJCWVsc2U6CgkJCWNvZGUuYXNzaWduKG5ld19jb2RlKQoJCXByaW50KGxlbihjb2RlKSA9PSBsZW4obmV3X2NvZGUpKQoAAAAAAAAAAAAAAAU= diff --git a/tests/cases/stable/storage/locking/modify_ctor.0_0.hash b/tests/cases/stable/storage/locking/modify_ctor.0_0.hash new file mode 100644 index 000000000..5316a6984 --- /dev/null +++ b/tests/cases/stable/storage/locking/modify_ctor.0_0.hash @@ -0,0 +1 @@ +LRFkZXhpdF9jb2RlIDMwAAUF diff --git a/tests/cases/stable/storage/locking/modify_later.0.hash b/tests/cases/stable/storage/locking/modify_later.0.hash new file mode 100644 index 000000000..d268241d5 --- /dev/null +++ b/tests/cases/stable/storage/locking/modify_later.0.hash @@ -0,0 +1 @@ +LQEAACUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAgwIBAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAroAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELAAAAAIM4cQMAACMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjp0ZXN0IiB9CgppbXBvcnQgZ2VubGF5ZXIgYXMgZ2wKZnJvbSBnZW5sYXllci50eXBlcyBpbXBvcnQgKgoKbmV3X2NvZGUgPSBiIiIiXAojIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQpwcmludCgiUGF0Y2hlZCEiKQpleGl0KDMwKQoiIiIKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglkZWYgX19pbml0X18oc2VsZiwgbW9kaWZpZXJzOiBsaXN0W0FkZHJlc3NdLCBtb2RpZnlfaW5fY3RvcjogYm9vbCk6CgkJcm9vdCA9IGdsLnN0b3JhZ2UuUm9vdC5nZXQoKQoJCXJvb3QudXBncmFkZXJzLmdldCgpLmV4dGVuZChtb2RpZmllcnMpCgoJCXNlbGYuc2hvd19pbmZvKCkKCgkJaWYgbW9kaWZ5X2luX2N0b3I6CgkJCXNlbGYudHJ5X21vZGlmeSgpCgoJZGVmIHNob3dfaW5mbyhzZWxmKToKCQlyb290ID0gZ2wuc3RvcmFnZS5Sb290LmdldCgpCgoJCXByaW50KGxpc3Qocm9vdC5sb2NrZWRfc2xvdHMuZ2V0KCkpKQoJCXByaW50KGxpc3Qocm9vdC51cGdyYWRlcnMuZ2V0KCkpKQoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBub3Aoc2VsZik6CgkJcGFzcwoKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiB0cnlfbW9kaWZ5KHNlbGYpOgoJCXJvb3QgPSBnbC5zdG9yYWdlLlJvb3QuZ2V0KCkKCgkJc2VsZi5zaG93X2luZm8oKQoKCQljb2RlID0gcm9vdC5jb2RlLmdldCgpCgkJdHJ5OgoJCQljb2RlLnRydW5jYXRlKCkgICMgPC0gd2Ugc2hvdWxkIGVuY291bnRlciBlcnJvciBoZXJlCgkJZXhjZXB0IEJhc2VFeGNlcHRpb24gYXMgZToKCQkJcHJpbnQoZSkKCQllbHNlOgoJCQljb2RlLmFzc2lnbihuZXdfY29kZSkKCQlwcmludChsZW4oY29kZSkgPT0gbGVuKG5ld19jb2RlKSkKAAAAAAAAAAAAAAAF diff --git a/tests/cases/stable/storage/locking/modify_later.0_0.hash b/tests/cases/stable/storage/locking/modify_later.0_0.hash new file mode 100644 index 000000000..729c97c3c --- /dev/null +++ b/tests/cases/stable/storage/locking/modify_later.0_0.hash @@ -0,0 +1 @@ +LQEAAA0VowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDBj8AAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQpwcmludCgiUGF0Y2hlZCEiKQpleGl0KDMwKQogZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCm5ldwU= diff --git a/tests/cases/stable/storage/locking/modify_later.0_0_0.hash b/tests/cases/stable/storage/locking/modify_later.0_0_0.hash new file mode 100644 index 000000000..5316a6984 --- /dev/null +++ b/tests/cases/stable/storage/locking/modify_later.0_0_0.hash @@ -0,0 +1 @@ +LRFkZXhpdF9jb2RlIDMwAAUF diff --git a/tests/cases/stable/storage/np.0.hash b/tests/cases/stable/storage/np.0.hash new file mode 100644 index 000000000..2360e5691 --- /dev/null +++ b/tests/cases/stable/storage/np.0.hash @@ -0,0 +1 @@ +LQEAABUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxyfAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCmltcG9ydCBudW1weSBhcyBucAoKaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCmZyb20gZ2VubGF5ZXIuc3RvcmFnZS5faW50ZXJuYWwuZ2VuZXJhdGUgaW1wb3J0IGdlbmVyYXRlX3N0b3JhZ2UKCgpAZ2VuZXJhdGVfc3RvcmFnZQpjbGFzcyBUZXN0OgoJZm9vOiBucC5mbG9hdDMyCgoJZGVmIGFiYyhzZWxmKToKCQlyZXR1cm4gc2VsZi5mb28KCgp0c3QgPSBUZXN0KCkKdHN0LmZvbyA9IG5wLmZsb2F0MzIoMC41KQoKYXNzZXJ0IHRzdC5mb28gPT0gMC41LCBmJ3t0c3QuZm9vfScKYXNzZXJ0IHR5cGUodHN0LmZvbykgaXMgbnAuZmxvYXQzMiwgZid7dHlwZSh0c3QuZm9vKX0nCnByaW50KHRzdC5mb28pCgpleGl0KDApCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/storage/persists.0.hash b/tests/cases/stable/storage/persists.0.hash new file mode 100644 index 000000000..6f4106281 --- /dev/null +++ b/tests/cases/stable/storage/persists.0.hash @@ -0,0 +1 @@ +LQEAAD0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCFuZj9tHg68Om6YF8z87pr6NnfZ7wLv4M7BSphMoY0c8AAAAAgwJhYmMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAiG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmAAAAAIMKBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQshueAT90YIuSlHhhKHs952wsB2/oObeZR2G9lQzC51ZiehXnRQ2fBOnD2NLYVqjpx436AIHqLBKP3JPOLfNevWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAoANXoZCs61EIpO/lWJghmmiq+WcVUZ8TAEyQcNXnQLaAAAAAIMEAQAAAAwAAAAAAAAAAgAAAAEDAAAAHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAq744hjkeWut5b9uW2fTvO39XzVEOvLEnDYFB22lgxghAAAAAIMCMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowK6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCwAAAACDFj4BAAAjIHsgIkRlcGVuZHMiOiAicHktZ2VubGF5ZXI6dGVzdCIgfQoKaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CgltOiBnbC5UcmVlTWFwW3N0ciwgdTMyXQoKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlwcmludCgnZmlyc3QnKQoJCXNlbGYubVsnMSddID0gMTIKCQlzZWxmLm1bJ2FiYyddID0gMzAKCglAZ2wucHVibGljLndyaXRlCglkZWYgc2Vjb25kKHNlbGYpOgoJCXByaW50KCdzZWNvbmQnKQoJCXByaW50KGxpc3Qoc2VsZi5tLml0ZW1zKCkpKQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDAgEAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/storage/persists.0_0.hash b/tests/cases/stable/storage/persists.0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/stable/storage/persists.0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/stable/storage/read_nondet.0.hash b/tests/cases/stable/storage/read_nondet.0.hash new file mode 100644 index 000000000..74ede8fe9 --- /dev/null +++ b/tests/cases/stable/storage/read_nondet.0.hash @@ -0,0 +1 @@ +LQEAAC0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCRqtO0me0YTFGMKUIKVN5qk+zOkFIIu6dcvDrLiymbsAAAAAAgwI0NTYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWjAroAVjB0Ws8wFKrxYumTMEAwLKC+8/Vv4tc8Cgj4LGELAAAAAIMUHQEAACMgeyAiRGVwZW5kcyI6ICJweS1nZW5sYXllcjpsYXRlc3QiIH0KCmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCgoKY2xhc3MgU3RvcmFnZShnbC5jb250cmFjdC5Db250cmFjdCk6CglhOiBzdHIKCglkZWYgX19pbml0X18oc2VsZik6CgkJc2VsZi5hID0gJzEyMycKCgkJZGVmIGYoKToKCQkJcHJpbnQoc2VsZi5hKQoKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGYpCgkJc2VsZi5hID0gJzQ1NicKCQlnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKGYpCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDAgMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/storage/storage_tree_map.0.hash b/tests/cases/stable/storage/storage_tree_map.0.hash new file mode 100644 index 000000000..ed6376cc4 --- /dev/null +++ b/tests/cases/stable/storage/storage_tree_map.0.hash @@ -0,0 +1 @@ +LQEAABUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxZIAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCmZyb20gZ2VubGF5ZXIuc3RvcmFnZS5faW50ZXJuYWwuZ2VuZXJhdGUgaW1wb3J0IGdlbmVyYXRlX3N0b3JhZ2UKCgpAZ2VuZXJhdGVfc3RvcmFnZQpjbGFzcyBVc2VyU3RvcmFnZToKCW06IGdsLlRyZWVNYXBbc3RyLCB1MzJdCgoKdHN0ID0gVXNlclN0b3JhZ2UoKQoKdHN0Lm1bJzEnXSA9IDEyCnRzdC5tWycyJ10gPSAxMwpkZWwgdHN0Lm1bJzEnXQpwcmludCgnMScgaW4gdHN0Lm0sIHRzdC5tWycyJ10pCgpleGl0KDApCgAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/stable/storage/to_str.0.hash b/tests/cases/stable/storage/to_str.0.hash new file mode 100644 index 000000000..f66e46468 --- /dev/null +++ b/tests/cases/stable/storage/to_str.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxZaAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCmZyb20gZ2VubGF5ZXIuc3RvcmFnZSBpbXBvcnQgYWxsb3cKCmZyb20gZGF0YWNsYXNzZXMgaW1wb3J0IGRhdGFjbGFzcwppbXBvcnQgZGF0ZXRpbWUKCgpAYWxsb3cKQGRhdGFjbGFzcwpjbGFzcyBVc2VyOgoJbmFtZTogc3RyCgliaXJ0aGRheTogZGF0ZXRpbWUuZGF0ZXRpbWUKCgpjbGFzcyBMbG1FcmMyMChnbC5jb250cmFjdC5Db250cmFjdCk6Cgl4OiBVc2VyCgoJZGVmIF9faW5pdF9fKHNlbGYpIC0+IE5vbmU6CgkJcHJpbnQoc3RyKHNlbGYueCkpCgAABQ== diff --git a/tests/cases/stable/storage/tree_map_nested.0.hash b/tests/cases/stable/storage/tree_map_nested.0.hash new file mode 100644 index 000000000..57761f016 --- /dev/null +++ b/tests/cases/stable/storage/tree_map_nested.0.hash @@ -0,0 +1 @@ +LQEAADUVowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCgA1ehkKzrUQik7+VYmCGaaKr5ZxVRnxMATJBw1edAtoAAAAAgwQAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMChsdvp6O6Dw79bsSR8qHqmLU0gx7ZM6Nyi70RXQnNAeoAAAAAgwQBAQEBAQEBAQEBAQEBAQEBAQEBAQ0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgx7MAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KCmltcG9ydCBnZW5sYXllciBhcyBnbApmcm9tIGdlbmxheWVyLnR5cGVzIGltcG9ydCAqCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJc3Q6IGdsLlRyZWVNYXBbQWRkcmVzcywgZ2wuVHJlZU1hcFtBZGRyZXNzLCB1MjU2XV0KCglkZWYgX19pbml0X18oc2VsZik6CgkJZmlyc3QgPSBzZWxmLnN0LmdldF9vcl9pbnNlcnRfZGVmYXVsdChBZGRyZXNzKGInXHgwMCcgKiAyMCkpCgkJcHJpbnQoe2suYXNfaGV4OiBkaWN0KHYuaXRlbXMoKSkgZm9yIGssIHYgaW4gc2VsZi5zdC5pdGVtcygpfSkKCQlwcmludChkaWN0KGZpcnN0Lml0ZW1zKCkpKQoJCWZpcnN0W0FkZHJlc3MoYidceDAxJyAqIDIwKV0gPSAxMwoJCXByaW50KHtrLmFzX2hleDogZGljdCh2Lml0ZW1zKCkpIGZvciBrLCB2IGluIHNlbGYuc3QuaXRlbXMoKX0pCgAAAAAAAAAAAAAAAAAAAAAVowLhriNBJ5Lfa2qY+3yYOXAfuLArb8ftAigQ94NGSUaF5wAAAACDAgEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/unstable/nondet/eq/ncomp/eq_prompt_non_comparative_validator.0.hash b/tests/cases/unstable/nondet/eq/ncomp/eq_prompt_non_comparative_validator.0.hash new file mode 100644 index 000000000..6d1554edf --- /dev/null +++ b/tests/cases/unstable/nondet/eq/ncomp/eq_prompt_non_comparative_validator.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgy7bAgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKaW1wb3J0IHN5cwoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlkZWYgZ2V0X2lucHV0KCk6CgkJCXJldHVybiAiQXMgcGV0cywgcmF0cyBhcmUgYWZmZWN0aW9uYXRlLCBwbGF5ZnVsLCBhbmQgZm9ybSBzdHJvbmcgYm9uZHMgd2l0aCB0aGVpciBodW1hbiBjb21wYW5pb25zLiBUaGV5J3JlIGN1cmlvdXMsIGVuam95IGludGVyYWN0aXZlIHRveXMsIGFuZCBjYW4gbGVhcm4gdHJpY2tzIG11Y2ggbGlrZSBzbWFsbCBkb2dzLiBUaGVpciBhZGFwdGFiaWxpdHksIGludGVsbGlnZW5jZSwgYW5kIGNoYXJtaW5nIHBlcnNvbmFsaXRpZXMgbWFrZSB0aGVtIHRydWx5IGNvb2wgYW5pbWFscyB0aGF0IGRlc2VydmUgbXVjaCBtb3JlIGFwcHJlY2lhdGlvbiB0aGFuIHRoZXkgY3VycmVudGx5IGdldC4iCgoJCXByaW50KAoJCQlnbC5lcV9wcmluY2lwbGUucHJvbXB0X25vbl9jb21wYXJhdGl2ZSgKCQkJCWdldF9pbnB1dCwKCQkJCXRhc2s9J1Byb2R1Y2UgYSB0ZXh0IHN1bW1hcnknLAoJCQkJY3JpdGVyaWE9J0l0IG11c3QgYmUgc2hvcnRlciB0aGFuIHRoZSBvcmlnaW5hbCB0ZXh0IGFuZCBiZSBhIHZhbGlkIHN1bW1hcnknLAoJCQkpLAoJCQlmaWxlPXN5cy5zdGRlcnIsCgkJKQoABQ== diff --git a/tests/cases/unstable/nondet/eq/ncomp/eq_prompt_non_comparative_validator_bad.0.hash b/tests/cases/unstable/nondet/eq/ncomp/eq_prompt_non_comparative_validator_bad.0.hash new file mode 100644 index 000000000..6d1554edf --- /dev/null +++ b/tests/cases/unstable/nondet/eq/ncomp/eq_prompt_non_comparative_validator_bad.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgy7bAgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKaW1wb3J0IHN5cwoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlkZWYgZ2V0X2lucHV0KCk6CgkJCXJldHVybiAiQXMgcGV0cywgcmF0cyBhcmUgYWZmZWN0aW9uYXRlLCBwbGF5ZnVsLCBhbmQgZm9ybSBzdHJvbmcgYm9uZHMgd2l0aCB0aGVpciBodW1hbiBjb21wYW5pb25zLiBUaGV5J3JlIGN1cmlvdXMsIGVuam95IGludGVyYWN0aXZlIHRveXMsIGFuZCBjYW4gbGVhcm4gdHJpY2tzIG11Y2ggbGlrZSBzbWFsbCBkb2dzLiBUaGVpciBhZGFwdGFiaWxpdHksIGludGVsbGlnZW5jZSwgYW5kIGNoYXJtaW5nIHBlcnNvbmFsaXRpZXMgbWFrZSB0aGVtIHRydWx5IGNvb2wgYW5pbWFscyB0aGF0IGRlc2VydmUgbXVjaCBtb3JlIGFwcHJlY2lhdGlvbiB0aGFuIHRoZXkgY3VycmVudGx5IGdldC4iCgoJCXByaW50KAoJCQlnbC5lcV9wcmluY2lwbGUucHJvbXB0X25vbl9jb21wYXJhdGl2ZSgKCQkJCWdldF9pbnB1dCwKCQkJCXRhc2s9J1Byb2R1Y2UgYSB0ZXh0IHN1bW1hcnknLAoJCQkJY3JpdGVyaWE9J0l0IG11c3QgYmUgc2hvcnRlciB0aGFuIHRoZSBvcmlnaW5hbCB0ZXh0IGFuZCBiZSBhIHZhbGlkIHN1bW1hcnknLAoJCQkpLAoJCQlmaWxlPXN5cy5zdGRlcnIsCgkJKQoABQ== diff --git a/tests/cases/unstable/nondet/validator/agree.0.hash b/tests/cases/unstable/nondet/validator/agree.0.hash new file mode 100644 index 000000000..b3bf463c3 --- /dev/null +++ b/tests/cases/unstable/nondet/validator/agree.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAg0ZQBAAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCmltcG9ydCBodG1sCmZyb20gaHRtbC5wYXJzZXIgaW1wb3J0IEhUTUxQYXJzZXIKCmZjZiA9IHNldChbJ3NjcmlwdCcsICdpZnJhbWUnXSkKCgpjbGFzcyBTY3JpcHRSZW1vdmVyKEhUTUxQYXJzZXIpOgoJcmVzdWx0OiBsaXN0W3N0cl0KCglkZWYgX19pbml0X18oc2VsZik6CgkJc3VwZXIoKS5fX2luaXRfXygpCgkJc2VsZi5yZXN1bHQgPSBbXQoJCXNlbGYuaW5fc2NyaXB0ID0gRmFsc2UKCglkZWYgaGFuZGxlX3N0YXJ0dGFnKHNlbGYsIHRhZywgYXR0cnMpOgoJCWlmIHRhZy5sb3dlcigpIGluIGZjZjoKCQkJc2VsZi5pbl9zY3JpcHQgPSBUcnVlCgkJZWxpZiBub3Qgc2VsZi5pbl9zY3JpcHQ6CgkJCXNlbGYucmVzdWx0LmFwcGVuZChzZWxmLmdldF9zdGFydHRhZ190ZXh0KCkpCgoJZGVmIGhhbmRsZV9lbmR0YWcoc2VsZiwgdGFnKToKCQlpZiB0YWcubG93ZXIoKSBpbiBmY2Y6CgkJCXNlbGYuaW5fc2NyaXB0ID0gRmFsc2UKCQllbGlmIG5vdCBzZWxmLmluX3NjcmlwdDoKCQkJc2VsZi5yZXN1bHQuYXBwZW5kKGYnPC97dGFnfT4nKQoKCWRlZiBoYW5kbGVfZGF0YShzZWxmLCBkYXRhKToKCQlpZiBub3Qgc2VsZi5pbl9zY3JpcHQ6CgkJCXNlbGYucmVzdWx0LmFwcGVuZChkYXRhKQoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYsIG1vZGU6IHN0cik6CgkJZGVmIHJ1bigpIC0+IHN0cjoKCQkJcmVzID0gZ2wubm9uZGV0LndlYi5yZW5kZXIoCgkJCQknaHR0cHM6Ly90ZXN0LXNlcnZlci5nZW5sYXllci5jb20vc3RhdGljL2dlbnZtL2hlbGxvLmh0bWwnLCBtb2RlPW1vZGUKCQkJKSAgIyB0eXBlOiBpZ25vcmUKCQkJaWYgbW9kZSA9PSAnaHRtbCc6CgkJCQlwYXJzZXIgPSBTY3JpcHRSZW1vdmVyKCkKCQkJCXBhcnNlci5mZWVkKHJlcykKCQkJCXJlcyA9ICcnLmpvaW4ocGFyc2VyLnJlc3VsdCkKCQkJcmV0dXJuIHJlcwoKCQlwcmludChnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKHJ1bikuc3RyaXAoKSkKAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/unstable/nondet/validator/agree.0_0.hash b/tests/cases/unstable/nondet/validator/agree.0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/unstable/nondet/validator/agree.0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/unstable/nondet/validator/disagree.0.hash b/tests/cases/unstable/nondet/validator/disagree.0.hash new file mode 100644 index 000000000..b3bf463c3 --- /dev/null +++ b/tests/cases/unstable/nondet/validator/disagree.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAg0ZQBAAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCmltcG9ydCBodG1sCmZyb20gaHRtbC5wYXJzZXIgaW1wb3J0IEhUTUxQYXJzZXIKCmZjZiA9IHNldChbJ3NjcmlwdCcsICdpZnJhbWUnXSkKCgpjbGFzcyBTY3JpcHRSZW1vdmVyKEhUTUxQYXJzZXIpOgoJcmVzdWx0OiBsaXN0W3N0cl0KCglkZWYgX19pbml0X18oc2VsZik6CgkJc3VwZXIoKS5fX2luaXRfXygpCgkJc2VsZi5yZXN1bHQgPSBbXQoJCXNlbGYuaW5fc2NyaXB0ID0gRmFsc2UKCglkZWYgaGFuZGxlX3N0YXJ0dGFnKHNlbGYsIHRhZywgYXR0cnMpOgoJCWlmIHRhZy5sb3dlcigpIGluIGZjZjoKCQkJc2VsZi5pbl9zY3JpcHQgPSBUcnVlCgkJZWxpZiBub3Qgc2VsZi5pbl9zY3JpcHQ6CgkJCXNlbGYucmVzdWx0LmFwcGVuZChzZWxmLmdldF9zdGFydHRhZ190ZXh0KCkpCgoJZGVmIGhhbmRsZV9lbmR0YWcoc2VsZiwgdGFnKToKCQlpZiB0YWcubG93ZXIoKSBpbiBmY2Y6CgkJCXNlbGYuaW5fc2NyaXB0ID0gRmFsc2UKCQllbGlmIG5vdCBzZWxmLmluX3NjcmlwdDoKCQkJc2VsZi5yZXN1bHQuYXBwZW5kKGYnPC97dGFnfT4nKQoKCWRlZiBoYW5kbGVfZGF0YShzZWxmLCBkYXRhKToKCQlpZiBub3Qgc2VsZi5pbl9zY3JpcHQ6CgkJCXNlbGYucmVzdWx0LmFwcGVuZChkYXRhKQoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYsIG1vZGU6IHN0cik6CgkJZGVmIHJ1bigpIC0+IHN0cjoKCQkJcmVzID0gZ2wubm9uZGV0LndlYi5yZW5kZXIoCgkJCQknaHR0cHM6Ly90ZXN0LXNlcnZlci5nZW5sYXllci5jb20vc3RhdGljL2dlbnZtL2hlbGxvLmh0bWwnLCBtb2RlPW1vZGUKCQkJKSAgIyB0eXBlOiBpZ25vcmUKCQkJaWYgbW9kZSA9PSAnaHRtbCc6CgkJCQlwYXJzZXIgPSBTY3JpcHRSZW1vdmVyKCkKCQkJCXBhcnNlci5mZWVkKHJlcykKCQkJCXJlcyA9ICcnLmpvaW4ocGFyc2VyLnJlc3VsdCkKCQkJcmV0dXJuIHJlcwoKCQlwcmludChnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKHJ1bikuc3RyaXAoKSkKAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/unstable/nondet/validator/disagree.0_0.hash b/tests/cases/unstable/nondet/validator/disagree.0_0.hash new file mode 100644 index 000000000..9942c2585 --- /dev/null +++ b/tests/cases/unstable/nondet/validator/disagree.0_0.hash @@ -0,0 +1 @@ +LQEAAAUF diff --git a/tests/cases/unstable/nondet/web/get_webpage_html.0.hash b/tests/cases/unstable/nondet/web/get_webpage_html.0.hash new file mode 100644 index 000000000..b3bf463c3 --- /dev/null +++ b/tests/cases/unstable/nondet/web/get_webpage_html.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAg0ZQBAAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCmltcG9ydCBodG1sCmZyb20gaHRtbC5wYXJzZXIgaW1wb3J0IEhUTUxQYXJzZXIKCmZjZiA9IHNldChbJ3NjcmlwdCcsICdpZnJhbWUnXSkKCgpjbGFzcyBTY3JpcHRSZW1vdmVyKEhUTUxQYXJzZXIpOgoJcmVzdWx0OiBsaXN0W3N0cl0KCglkZWYgX19pbml0X18oc2VsZik6CgkJc3VwZXIoKS5fX2luaXRfXygpCgkJc2VsZi5yZXN1bHQgPSBbXQoJCXNlbGYuaW5fc2NyaXB0ID0gRmFsc2UKCglkZWYgaGFuZGxlX3N0YXJ0dGFnKHNlbGYsIHRhZywgYXR0cnMpOgoJCWlmIHRhZy5sb3dlcigpIGluIGZjZjoKCQkJc2VsZi5pbl9zY3JpcHQgPSBUcnVlCgkJZWxpZiBub3Qgc2VsZi5pbl9zY3JpcHQ6CgkJCXNlbGYucmVzdWx0LmFwcGVuZChzZWxmLmdldF9zdGFydHRhZ190ZXh0KCkpCgoJZGVmIGhhbmRsZV9lbmR0YWcoc2VsZiwgdGFnKToKCQlpZiB0YWcubG93ZXIoKSBpbiBmY2Y6CgkJCXNlbGYuaW5fc2NyaXB0ID0gRmFsc2UKCQllbGlmIG5vdCBzZWxmLmluX3NjcmlwdDoKCQkJc2VsZi5yZXN1bHQuYXBwZW5kKGYnPC97dGFnfT4nKQoKCWRlZiBoYW5kbGVfZGF0YShzZWxmLCBkYXRhKToKCQlpZiBub3Qgc2VsZi5pbl9zY3JpcHQ6CgkJCXNlbGYucmVzdWx0LmFwcGVuZChkYXRhKQoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYsIG1vZGU6IHN0cik6CgkJZGVmIHJ1bigpIC0+IHN0cjoKCQkJcmVzID0gZ2wubm9uZGV0LndlYi5yZW5kZXIoCgkJCQknaHR0cHM6Ly90ZXN0LXNlcnZlci5nZW5sYXllci5jb20vc3RhdGljL2dlbnZtL2hlbGxvLmh0bWwnLCBtb2RlPW1vZGUKCQkJKSAgIyB0eXBlOiBpZ25vcmUKCQkJaWYgbW9kZSA9PSAnaHRtbCc6CgkJCQlwYXJzZXIgPSBTY3JpcHRSZW1vdmVyKCkKCQkJCXBhcnNlci5mZWVkKHJlcykKCQkJCXJlcyA9ICcnLmpvaW4ocGFyc2VyLnJlc3VsdCkKCQkJcmV0dXJuIHJlcwoKCQlwcmludChnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKHJ1bikuc3RyaXAoKSkKAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/unstable/nondet/web/get_webpage_screenshot.0.hash b/tests/cases/unstable/nondet/web/get_webpage_screenshot.0.hash new file mode 100644 index 000000000..eeba6163b --- /dev/null +++ b/tests/cases/unstable/nondet/web/get_webpage_screenshot.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgyZLAgAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCmltcG9ydCBzeXMKCgpjbGFzcyBDb250cmFjdChnbC5jb250cmFjdC5Db250cmFjdCk6CglAZ2wucHVibGljLndyaXRlCglkZWYgbWFpbihzZWxmLCBtb2RlOiBzdHIpOgoJCWRlZiBydW4oKToKCQkJaW1nID0gZ2wubm9uZGV0LndlYi5yZW5kZXIoCgkJCQknaHR0cHM6Ly90ZXN0LXNlcnZlci5nZW5sYXllci5jb20vc3RhdGljL2dlbnZtL2hlbGxvLmh0bWwnLCBtb2RlPSdzY3JlZW5zaG90JwoJCQkpCgoJCQlyZXMgPSBnbC5ub25kZXQuZXhlY19wcm9tcHQoCgkJCQknd2hhdCBpbWFnZSBzYXlzPyByZXNwb25kIG9ubHkgd2l0aCBpdHMgY29udGVudHMnLCBpbWFnZXM9W2ltZ10KCQkJKQoKCQkJcmV0dXJuICcnLmpvaW4oYyBmb3IgYyBpbiByZXMuc3RyaXAoKS5sb3dlcigpIGlmIGMuaXNhbHBoYSgpKQoKCQlyZXMgPSBnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKHJ1bikKCQlwcmludChyZXMsIGZpbGU9c3lzLnN0ZGVycikKCQlwcmludCgnaGVsbG93b3JsZCcgaW4gcmVzKQoAAAAAAAAAAAAAAAAAAAAAAAU= diff --git a/tests/cases/unstable/nondet/web/get_webpage_text.0.hash b/tests/cases/unstable/nondet/web/get_webpage_text.0.hash new file mode 100644 index 000000000..b3bf463c3 --- /dev/null +++ b/tests/cases/unstable/nondet/web/get_webpage_text.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAg0ZQBAAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCmltcG9ydCBodG1sCmZyb20gaHRtbC5wYXJzZXIgaW1wb3J0IEhUTUxQYXJzZXIKCmZjZiA9IHNldChbJ3NjcmlwdCcsICdpZnJhbWUnXSkKCgpjbGFzcyBTY3JpcHRSZW1vdmVyKEhUTUxQYXJzZXIpOgoJcmVzdWx0OiBsaXN0W3N0cl0KCglkZWYgX19pbml0X18oc2VsZik6CgkJc3VwZXIoKS5fX2luaXRfXygpCgkJc2VsZi5yZXN1bHQgPSBbXQoJCXNlbGYuaW5fc2NyaXB0ID0gRmFsc2UKCglkZWYgaGFuZGxlX3N0YXJ0dGFnKHNlbGYsIHRhZywgYXR0cnMpOgoJCWlmIHRhZy5sb3dlcigpIGluIGZjZjoKCQkJc2VsZi5pbl9zY3JpcHQgPSBUcnVlCgkJZWxpZiBub3Qgc2VsZi5pbl9zY3JpcHQ6CgkJCXNlbGYucmVzdWx0LmFwcGVuZChzZWxmLmdldF9zdGFydHRhZ190ZXh0KCkpCgoJZGVmIGhhbmRsZV9lbmR0YWcoc2VsZiwgdGFnKToKCQlpZiB0YWcubG93ZXIoKSBpbiBmY2Y6CgkJCXNlbGYuaW5fc2NyaXB0ID0gRmFsc2UKCQllbGlmIG5vdCBzZWxmLmluX3NjcmlwdDoKCQkJc2VsZi5yZXN1bHQuYXBwZW5kKGYnPC97dGFnfT4nKQoKCWRlZiBoYW5kbGVfZGF0YShzZWxmLCBkYXRhKToKCQlpZiBub3Qgc2VsZi5pbl9zY3JpcHQ6CgkJCXNlbGYucmVzdWx0LmFwcGVuZChkYXRhKQoKCmNsYXNzIENvbnRyYWN0KGdsLmNvbnRyYWN0LkNvbnRyYWN0KToKCUBnbC5wdWJsaWMud3JpdGUKCWRlZiBtYWluKHNlbGYsIG1vZGU6IHN0cik6CgkJZGVmIHJ1bigpIC0+IHN0cjoKCQkJcmVzID0gZ2wubm9uZGV0LndlYi5yZW5kZXIoCgkJCQknaHR0cHM6Ly90ZXN0LXNlcnZlci5nZW5sYXllci5jb20vc3RhdGljL2dlbnZtL2hlbGxvLmh0bWwnLCBtb2RlPW1vZGUKCQkJKSAgIyB0eXBlOiBpZ25vcmUKCQkJaWYgbW9kZSA9PSAnaHRtbCc6CgkJCQlwYXJzZXIgPSBTY3JpcHRSZW1vdmVyKCkKCQkJCXBhcnNlci5mZWVkKHJlcykKCQkJCXJlcyA9ICcnLmpvaW4ocGFyc2VyLnJlc3VsdCkKCQkJcmV0dXJuIHJlcwoKCQlwcmludChnbC5lcV9wcmluY2lwbGUuc3RyaWN0X2VxKHJ1bikuc3RyaXAoKSkKAAAAAAAAAAAAAAAABQ== diff --git a/tests/cases/unstable/nondet/web/sandbox.0.hash b/tests/cases/unstable/nondet/web/sandbox.0.hash new file mode 100644 index 000000000..c0d168136 --- /dev/null +++ b/tests/cases/unstable/nondet/web/sandbox.0.hash @@ -0,0 +1 @@ +LQEAAB0VowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCIbngE/dGCLkpR4YSh7PedsLAdv6Dm3mUdhvZUMwudWYAAAAAgwoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6AFYwdFrPMBSq8WLpkzBAMCygvvP1b+LXPAoI+CxhCyG54BP3Rgi5KUeGEoez3nbCwHb+g5t5lHYb2VDMLnVmJ6FedFDZ8E6cPY0thWqOnHjfoAgeosEo/ck84t8169YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaMCugBWMHRazzAUqvFi6ZMwQDAsoL7z9W/i1zwKCPgsYQsAAAAAgxZcAQAAIyB7ICJEZXBlbmRzIjogInB5LWdlbmxheWVyOnRlc3QiIH0KaW1wb3J0IGdlbmxheWVyIGFzIGdsCmZyb20gZ2VubGF5ZXIudHlwZXMgaW1wb3J0ICoKCmltcG9ydCBqc29uCgoKY2xhc3MgQ29udHJhY3QoZ2wuY29udHJhY3QuQ29udHJhY3QpOgoJQGdsLnB1YmxpYy53cml0ZQoJZGVmIG1haW4oc2VsZiwgZXY6IHN0cik6CgkJZGVmIHJ1bl9uZGV0KCk6CgkJCWdsYiA9IGdsb2JhbHMoKQoJCQlwcmludChmJ3tnbC52bS5zcGF3bl9zYW5kYm94KGxhbWJkYTogZXZhbChldiwgZ2xiKSl9JykKCQkJcHJpbnQoanNvbi5sb2Fkcy5fX25hbWVfXykKCgkJZ2wuZXFfcHJpbmNpcGxlLnN0cmljdF9lcShydW5fbmRldCkKBQ==