From 3cf1c9ace19eefe5719e20181792274572a48c48 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 9 May 2025 22:37:07 +0200 Subject: [PATCH 1/4] feat: add an article about crossing Signed-off-by: moul <94029+moul@users.noreply.github.com> --- posts/2025-05-xx_crossing_manfred/README.md | 115 ++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 posts/2025-05-xx_crossing_manfred/README.md diff --git a/posts/2025-05-xx_crossing_manfred/README.md b/posts/2025-05-xx_crossing_manfred/README.md new file mode 100644 index 0000000..7ac7a99 --- /dev/null +++ b/posts/2025-05-xx_crossing_manfred/README.md @@ -0,0 +1,115 @@ +--- +publication_date: 2025-05-XXXT00:00:00Z +slug: XXX +tags: [gnovm] +authors: [manfred] +--- + +## Interrealm Calls vs. Traditional Microservices: A Paradigm Shift + +Understanding Gno's interrealm call mechanism can be simplified by comparing it to the familiar concept of microservices in traditional distributed systems. While both aim to modularize functionality, Gno offers a fundamentally simpler, more robust, and integrated approach. + +### The Traditional Microservice Experience + +In typical microservice architectures (e.g., using gRPC, REST APIs), developers face several inherent complexities: + +1. **Connection Management:** Explicit steps are needed to establish connections (e.g., `grpc.Dial`, HTTP client setup). These connections can fail due to network issues, configuration errors, or service unavailability, requiring dedicated error handling. +2. **Network Failures:** A call to a remote service can fail *not only* because the service's logic encountered an error, but also due to transient network problems, timeouts, or infrastructure issues. Distinguishing between these failure modes adds complexity. +3. **Data Serialization:** Data exchanged between services must often be explicitly serialized and deserialized into primitive types or specific formats (e.g., JSON, Protobuf). Passing complex objects or pointers directly is generally not possible. +4. **Manual Transaction Management:** Ensuring atomicity across multiple service calls is notoriously difficult. If a sequence of calls needs to succeed or fail together, developers must implement complex rollback or compensation logic. For example, if Service A succeeds but a subsequent call to Service B fails, the developer is responsible for: + * Rolling back local state changes. + * Potentially calling Service A again with a compensating action to undo its previous operation. + This manual coordination is error-prone and can lead to inconsistent states, often requiring complex distributed locking mechanisms. +5. **Language/Protocol Proliferation:** Developers typically need to master the primary programming language *plus* various data formats (JSON, Protobuf, XML) and potentially interface definition languages (IDLs). + +```ascii + Traditional Microservices: + + [Your App] ------> Connect() -----> [Network] ------> [Service A] + | | | | + |---< Fail? <-----| | | + | | | | + +-----> Call(primitive) -> Marshal -> + -> Unmarshal -> +---> Logic A ---+ + | | | | | + |<---- Fail? <----|<---- Fail? <-----| |<--- Logic OK --+ + | | | | + +-----> Call(primitive) -> Marshal -> + -> Unmarshal -> [Service B] ---> Logic B ---+ + | | | | | + |<---- Fail? <----|<---- Fail? <-----| |<--------- Logic FAIL! -----+ + | | + +---> // Now what? Manually rollback state? | + | // Call Service A again to compensate? | + +------------------------------------------------------+ +``` + +### The Gno Interrealm Experience + +Gno's interrealm calls, facilitated by the GnoVM, provide a seamless and powerful alternative, akin to an idealized microservice architecture: + +1. **Transparent Connection:** The "connection" between realms is managed implicitly by the GnoVM. There's no separate connection step to manage or fail. +2. **Reliable Calls (Logic-Centric Failures):** Interrealm calls abstract away network failures. A call fails *only* if the logic within the called realm's function panics or returns an error. The underlying transport is guaranteed by the VM and the consensus layer. +3. **Rich Data Types:** Gno allows passing complex data types, including slices, maps, structs, and even pointers (with specific rules), directly between realms without manual serialization/deserialization. +4. **Automatic Atomic Transactions:** This is a major advantage. All operations within a Gno transaction, including multiple interrealm calls across different realms, are atomic. If *any* part of the transaction fails (e.g., a panic in one of the called realms), the *entire* transaction is automatically rolled back by the GnoVM. There is no need for manual compensation logic; consistency is guaranteed at the VM level. +5. **Unified Language:** Developers only need to know Gno. The language used for writing realm logic is the same language used for making interrealm calls. No separate IDLs or data formats are required. + +```ascii + Gno Interrealm Call: + + [Realm A] ----> call_other_realm(complex_type) ----> [GnoVM Manages Interaction] ----> [Realm B] + | ^ | + | | | + | +-------------------- Logic OK ------------------------------+ + | | + +----------------------------------- Logic OK -------------------------------------+ + + // OR, if Realm B fails: + + [Realm A] ----> call_other_realm(complex_type) ----> [GnoVM Manages Interaction] ----> [Realm B] + | ^ | + | | X<--- Logic Panic! + | +--------------------- Panic Bubbles ------------------------+ + | + X<----------- GnoVM Automatically Rolls Back ENTIRE Transaction -------------------+ + +``` + +In essence, Gno provides the "best microservice experience" imaginable: simple, highly composable, robust error handling, and automatic transactional consistency, all within a single language and runtime environment. This opens the door to powerful new patterns of code reuse and composability directly on the blockchain. + +### Understanding `cross` and `crossing` + +While basic interrealm calls provide access to another realm's functions and data (read-only), the optional `cross` keyword and `crossing()` function modifier introduce control over the execution *context*. + +* **Calling without `cross` (Non-crossing call):** When you call a function in another realm *without* using `cross`, you are essentially executing that remote code within your *current* realm's context and memory space (though direct modification of the remote realm's state is restricted). Think of it like borrowing a library from another service but running it locally. + + ```ascii + Non-crossing Call (Realm A calls Realm B's function): + + [Realm A Context]------------+ + | | + | Executes Realm B's code | + | (within Realm A's context) | + | | + +----------------------------+ + | + | Reads data from + V + [Realm B State] (Read-Only Access) + ``` + +* **Calling with `cross` (Crossing call):** When you call a `crossing()` function using the `cross(realmB.Function)(...)` syntax, you explicitly shift the execution context *into* the target realm (Realm B). The function now executes with Realm B's permissions, environment (`std.CurrentRealm()` changes), and can directly modify Realm B's state. This is like truly entering the other microservice's environment to perform an operation. + + ```ascii + Crossing Call (Realm A calls Realm B's crossing function): + + [Realm A Context] --cross()--> [Realm B Context]----------+ + | | + | Executes Realm B's code | + | (within Realm B's context)| + | Can modify Realm B State | + | | + [Realm A State] <----return----+- std.CurrentRealm() is B -+ + | | + +--------------------------+ + ``` + +This distinction allows fine-grained control over permissions, state modifications, and resource usage during interrealm interactions, further enhancing the Gno programming model's capabilities beyond traditional systems. \ No newline at end of file From a5ede44bffe65852f21ba6194f10e20b5438abbc Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 9 May 2025 22:45:48 +0200 Subject: [PATCH 2/4] chore: fixup --- posts/2025-05-xx_crossing_manfred/README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/posts/2025-05-xx_crossing_manfred/README.md b/posts/2025-05-xx_crossing_manfred/README.md index 7ac7a99..3ef188f 100644 --- a/posts/2025-05-xx_crossing_manfred/README.md +++ b/posts/2025-05-xx_crossing_manfred/README.md @@ -79,7 +79,7 @@ In essence, Gno provides the "best microservice experience" imaginable: simple, While basic interrealm calls provide access to another realm's functions and data (read-only), the optional `cross` keyword and `crossing()` function modifier introduce control over the execution *context*. -* **Calling without `cross` (Non-crossing call):** When you call a function in another realm *without* using `cross`, you are essentially executing that remote code within your *current* realm's context and memory space (though direct modification of the remote realm's state is restricted). Think of it like borrowing a library from another service but running it locally. +* **Calling without `cross` (Non-crossing call):** When you call a function in another realm *without* using `cross`, you are essentially executing that remote code within your *current* realm's context and memory space. Direct modification of the remote realm's state is restricted. Think of it like borrowing a library from another service but running it locally. Trying to modify memory of another realm without `cross` is forbidden and will result in a panic. For example, if Realm A calls a function in Realm B that attempts `realmB.someState = "new value"`, this operation will fail if not done within a `crossing()` call. ```ascii Non-crossing Call (Realm A calls Realm B's function): @@ -96,7 +96,7 @@ While basic interrealm calls provide access to another realm's functions and dat [Realm B State] (Read-Only Access) ``` -* **Calling with `cross` (Crossing call):** When you call a `crossing()` function using the `cross(realmB.Function)(...)` syntax, you explicitly shift the execution context *into* the target realm (Realm B). The function now executes with Realm B's permissions, environment (`std.CurrentRealm()` changes), and can directly modify Realm B's state. This is like truly entering the other microservice's environment to perform an operation. +* **Calling with `cross` (Crossing call):** When you call a `crossing()` function using the `cross(realmB.Function)(...)` syntax, you explicitly shift the execution context *into* the target realm (Realm B). The function now executes with Realm B's permissions, environment (`std.CurrentRealm()` changes), and can directly modify Realm B's state. This is like truly entering the other microservice's environment to perform an operation; Realm A is allowed to modify Realm B's memory, but this modification happens within Realm B's context. ```ascii Crossing Call (Realm A calls Realm B's crossing function): @@ -112,4 +112,10 @@ While basic interrealm calls provide access to another realm's functions and dat +--------------------------+ ``` +### Advanced Scenarios: Circular Crossing and Indirect Invocation + +A common question is: What if Realm A crosses into Realm B, and then Realm B attempts to cross back into Realm A within the same transaction? While a direct circular import between realm packages is disallowed at compile time, a circular *call* sequence (A -> B -> A) during a crossing call is more nuanced. When B calls back into A, the context shifts *again*. It's not as if A never crossed; rather, it's a nested context change. The execution is now in Realm A's context, but this is a *new* context initiated by Realm B. `std.CurrentRealm()` would reflect Realm A, and modifications would apply to Realm A's state. However, the overall transaction's atomicity is still managed by the GnoVM. If any part of this A -> B -> A sequence fails, the entire set of operations across all involved realms is rolled back. + +Furthermore, while direct two-sided *imports* between realm packages are disallowed at compile time, callback-style interactions are directly achievable. Realm A can pass an object instance (which includes methods) or a function reference to Realm B as part of a `cross` call. Subsequently, Realm B can invoke a method on this passed object or call the function. Such an invocation targeting code originating from Realm A will execute within Realm A's context. This allows Realm B to trigger computations or state modifications back in Realm A, effectively creating a callback. This mechanism supports sophisticated, direct interactions where realms can influence each other's state within a single atomic transaction, without necessarily requiring an intermediary realm. + This distinction allows fine-grained control over permissions, state modifications, and resource usage during interrealm interactions, further enhancing the Gno programming model's capabilities beyond traditional systems. \ No newline at end of file From ce6b5ec65d7c5151dafde5ce3ed36f3ea48afc35 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 9 May 2025 22:54:51 +0200 Subject: [PATCH 3/4] chore: fixup --- posts/2025-05-xx_crossing_manfred/README.md | 135 ++++++++++++++------ 1 file changed, 98 insertions(+), 37 deletions(-) diff --git a/posts/2025-05-xx_crossing_manfred/README.md b/posts/2025-05-xx_crossing_manfred/README.md index 3ef188f..2ce4612 100644 --- a/posts/2025-05-xx_crossing_manfred/README.md +++ b/posts/2025-05-xx_crossing_manfred/README.md @@ -5,22 +5,43 @@ tags: [gnovm] authors: [manfred] --- -## Interrealm Calls vs. Traditional Microservices: A Paradigm Shift - -Understanding Gno's interrealm call mechanism can be simplified by comparing it to the familiar concept of microservices in traditional distributed systems. While both aim to modularize functionality, Gno offers a fundamentally simpler, more robust, and integrated approach. - -### The Traditional Microservice Experience - -In typical microservice architectures (e.g., using gRPC, REST APIs), developers face several inherent complexities: - -1. **Connection Management:** Explicit steps are needed to establish connections (e.g., `grpc.Dial`, HTTP client setup). These connections can fail due to network issues, configuration errors, or service unavailability, requiring dedicated error handling. -2. **Network Failures:** A call to a remote service can fail *not only* because the service's logic encountered an error, but also due to transient network problems, timeouts, or infrastructure issues. Distinguishing between these failure modes adds complexity. -3. **Data Serialization:** Data exchanged between services must often be explicitly serialized and deserialized into primitive types or specific formats (e.g., JSON, Protobuf). Passing complex objects or pointers directly is generally not possible. -4. **Manual Transaction Management:** Ensuring atomicity across multiple service calls is notoriously difficult. If a sequence of calls needs to succeed or fail together, developers must implement complex rollback or compensation logic. For example, if Service A succeeds but a subsequent call to Service B fails, the developer is responsible for: - * Rolling back local state changes. - * Potentially calling Service A again with a compensating action to undo its previous operation. - This manual coordination is error-prone and can lead to inconsistent states, often requiring complex distributed locking mechanisms. -5. **Language/Protocol Proliferation:** Developers typically need to master the primary programming language *plus* various data formats (JSON, Protobuf, XML) and potentially interface definition languages (IDLs). +# Interrealm Calls vs. Traditional Microservices: A Paradigm Shift + +Understanding Gno's interrealm call mechanism can be simplified by comparing it +to the familiar concept of microservices in traditional distributed systems. +While both aim to modularize functionality, Gno offers a fundamentally simpler, +more robust, and integrated approach. + +## The Traditional Microservice Experience + +In typical microservice architectures (e.g., using gRPC, REST APIs), developers +face several inherent complexities: + +1. **Connection Management:** Explicit steps are needed to establish connections + (e.g., `grpc.Dial`, HTTP client setup). These connections can fail due to + network issues, configuration errors, or service unavailability, requiring + dedicated error handling. +2. **Network Failures:** A call to a remote service can fail *not only* because + the service's logic encountered an error, but also due to transient network + problems, timeouts, or infrastructure issues. Distinguishing between these + failure modes adds complexity. +3. **Data Serialization:** Data exchanged between services must often be + explicitly serialized and deserialized into primitive types or specific + formats (e.g., JSON, Protobuf). Passing complex objects or pointers directly + is generally not possible. +4. **Manual Transaction Management:** Ensuring atomicity across multiple service + calls is notoriously difficult. If a sequence of calls needs to succeed or + fail together, developers must implement complex rollback or compensation + logic. For example, if Service A succeeds but a subsequent call to Service B + fails, the developer is responsible for: + * Rolling back local state changes. + * Potentially calling Service A again with a compensating action to undo its + previous operation. + This manual coordination is error-prone and can lead to inconsistent states, + often requiring complex distributed locking mechanisms. +5. **Language/Protocol Proliferation:** Developers typically need to master the + primary programming language *plus* various data formats (JSON, Protobuf, + XML) and potentially interface definition languages (IDLs). ```ascii Traditional Microservices: @@ -42,15 +63,30 @@ In typical microservice architectures (e.g., using gRPC, REST APIs), developers +------------------------------------------------------+ ``` -### The Gno Interrealm Experience - -Gno's interrealm calls, facilitated by the GnoVM, provide a seamless and powerful alternative, akin to an idealized microservice architecture: - -1. **Transparent Connection:** The "connection" between realms is managed implicitly by the GnoVM. There's no separate connection step to manage or fail. -2. **Reliable Calls (Logic-Centric Failures):** Interrealm calls abstract away network failures. A call fails *only* if the logic within the called realm's function panics or returns an error. The underlying transport is guaranteed by the VM and the consensus layer. -3. **Rich Data Types:** Gno allows passing complex data types, including slices, maps, structs, and even pointers (with specific rules), directly between realms without manual serialization/deserialization. -4. **Automatic Atomic Transactions:** This is a major advantage. All operations within a Gno transaction, including multiple interrealm calls across different realms, are atomic. If *any* part of the transaction fails (e.g., a panic in one of the called realms), the *entire* transaction is automatically rolled back by the GnoVM. There is no need for manual compensation logic; consistency is guaranteed at the VM level. -5. **Unified Language:** Developers only need to know Gno. The language used for writing realm logic is the same language used for making interrealm calls. No separate IDLs or data formats are required. +## The Gno Interrealm Experience + +Gno's interrealm calls, facilitated by the GnoVM, provide a seamless and +powerful alternative, akin to an idealized microservice architecture: + +1. **Transparent Connection:** The "connection" between realms is managed + implicitly by the GnoVM. There's no separate connection step to manage or + fail. +2. **Reliable Calls (Logic-Centric Failures):** Interrealm calls abstract away + network failures. A call fails *only* if the logic within the called realm's + function panics or returns an error. The underlying transport is guaranteed + by the VM and the consensus layer. +3. **Rich Data Types:** Gno allows passing complex data types, including slices, + maps, structs, and even pointers (with specific rules), directly between + realms without manual serialization/deserialization. +4. **Automatic Atomic Transactions:** This is a major advantage. All operations + within a Gno transaction, including multiple interrealm calls across + different realms, are atomic. If *any* part of the transaction fails (e.g., + a panic in one of the called realms), the *entire* transaction is + automatically rolled back by the GnoVM. There is no need for manual + compensation logic; consistency is guaranteed at the VM level. +5. **Unified Language:** Developers only need to know Gno. The language used for + writing realm logic is the same language used for making interrealm calls. + No separate IDLs or data formats are required. ```ascii Gno Interrealm Call: @@ -73,13 +109,27 @@ Gno's interrealm calls, facilitated by the GnoVM, provide a seamless and powerfu ``` -In essence, Gno provides the "best microservice experience" imaginable: simple, highly composable, robust error handling, and automatic transactional consistency, all within a single language and runtime environment. This opens the door to powerful new patterns of code reuse and composability directly on the blockchain. +In essence, Gno provides the "best microservice experience" imaginable: simple, +highly composable, robust error handling, and automatic transactional +consistency, all within a single language and runtime environment. This opens +the door to powerful new patterns of code reuse and composability directly on +the blockchain. -### Understanding `cross` and `crossing` +## Understanding `cross` and `crossing` -While basic interrealm calls provide access to another realm's functions and data (read-only), the optional `cross` keyword and `crossing()` function modifier introduce control over the execution *context*. +While basic interrealm calls provide access to another realm's functions and +data (read-only), the optional `cross` keyword and `crossing()` function +modifier introduce control over the execution *context*. -* **Calling without `cross` (Non-crossing call):** When you call a function in another realm *without* using `cross`, you are essentially executing that remote code within your *current* realm's context and memory space. Direct modification of the remote realm's state is restricted. Think of it like borrowing a library from another service but running it locally. Trying to modify memory of another realm without `cross` is forbidden and will result in a panic. For example, if Realm A calls a function in Realm B that attempts `realmB.someState = "new value"`, this operation will fail if not done within a `crossing()` call. +* **Calling without `cross` (Non-crossing call):** When you call a function in + another realm *without* using `cross`, you are essentially executing that + remote code within your *current* realm's context and memory space. Direct + modification of the remote realm's state is restricted. Think of it like + borrowing a library from another service but running it locally. Trying to + modify memory of another realm without `cross` is forbidden and will result in + a panic. For example, if Realm A calls a function in Realm B that attempts + `realmB.someState = "new value"`, this operation will fail if not done within + a `crossing()` call. ```ascii Non-crossing Call (Realm A calls Realm B's function): @@ -96,7 +146,14 @@ While basic interrealm calls provide access to another realm's functions and dat [Realm B State] (Read-Only Access) ``` -* **Calling with `cross` (Crossing call):** When you call a `crossing()` function using the `cross(realmB.Function)(...)` syntax, you explicitly shift the execution context *into* the target realm (Realm B). The function now executes with Realm B's permissions, environment (`std.CurrentRealm()` changes), and can directly modify Realm B's state. This is like truly entering the other microservice's environment to perform an operation; Realm A is allowed to modify Realm B's memory, but this modification happens within Realm B's context. +* **Calling with `cross` (Crossing call):** When you call a `crossing()` + function using the `cross(realmB.Function)(...)` syntax, you explicitly shift + the execution context *into* the target realm (Realm B). The function now + executes with Realm B's permissions, environment (`std.CurrentRealm()` + changes), and can directly modify Realm B's state. This is like truly entering + the other microservice's environment to perform an operation; Realm A is + allowed to modify Realm B's memory, but this modification happens within Realm + B's context. ```ascii Crossing Call (Realm A calls Realm B's crossing function): @@ -112,10 +169,14 @@ While basic interrealm calls provide access to another realm's functions and dat +--------------------------+ ``` -### Advanced Scenarios: Circular Crossing and Indirect Invocation - -A common question is: What if Realm A crosses into Realm B, and then Realm B attempts to cross back into Realm A within the same transaction? While a direct circular import between realm packages is disallowed at compile time, a circular *call* sequence (A -> B -> A) during a crossing call is more nuanced. When B calls back into A, the context shifts *again*. It's not as if A never crossed; rather, it's a nested context change. The execution is now in Realm A's context, but this is a *new* context initiated by Realm B. `std.CurrentRealm()` would reflect Realm A, and modifications would apply to Realm A's state. However, the overall transaction's atomicity is still managed by the GnoVM. If any part of this A -> B -> A sequence fails, the entire set of operations across all involved realms is rolled back. - -Furthermore, while direct two-sided *imports* between realm packages are disallowed at compile time, callback-style interactions are directly achievable. Realm A can pass an object instance (which includes methods) or a function reference to Realm B as part of a `cross` call. Subsequently, Realm B can invoke a method on this passed object or call the function. Such an invocation targeting code originating from Realm A will execute within Realm A's context. This allows Realm B to trigger computations or state modifications back in Realm A, effectively creating a callback. This mechanism supports sophisticated, direct interactions where realms can influence each other's state within a single atomic transaction, without necessarily requiring an intermediary realm. - -This distinction allows fine-grained control over permissions, state modifications, and resource usage during interrealm interactions, further enhancing the Gno programming model's capabilities beyond traditional systems. \ No newline at end of file +A common question is: What if Realm A crosses into Realm B, and then Realm B +attempts to cross back into Realm A within the same transaction? While a direct +circular import between realm packages is disallowed at compile time, a circular +*call* sequence (A -> B -> A) during a crossing call is more nuanced. When B +calls back into A, the context shifts *again*. It's not as if A never crossed; +rather, it's a nested context change. The execution is now in Realm A's context, +but this is a *new* context initiated by Realm B. `std.CurrentRealm()` would +reflect Realm A, and modifications would apply to Realm A's state. However, the +overall transaction's atomicity is still managed by the GnoVM. If any part of +this A -> B -> A sequence fails, the entire set of operations across all +involved realms is rolled back. \ No newline at end of file From 5e38472755c851c968961eb13dfd9fd185a2b217 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 9 May 2025 22:57:15 +0200 Subject: [PATCH 4/4] chore: fixup --- posts/2025-05-xx_crossing_manfred/README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/posts/2025-05-xx_crossing_manfred/README.md b/posts/2025-05-xx_crossing_manfred/README.md index 2ce4612..233acb7 100644 --- a/posts/2025-05-xx_crossing_manfred/README.md +++ b/posts/2025-05-xx_crossing_manfred/README.md @@ -51,8 +51,8 @@ face several inherent complexities: |---< Fail? <-----| | | | | | | +-----> Call(primitive) -> Marshal -> + -> Unmarshal -> +---> Logic A ---+ - | | | | | - |<---- Fail? <----|<---- Fail? <-----| |<--- Logic OK --+ + | | | | | + |<---- Fail? <----|<---- Fail? <-----| |<--- Logic OK ---+ | | | | +-----> Call(primitive) -> Marshal -> + -> Unmarshal -> [Service B] ---> Logic B ---+ | | | | | @@ -158,15 +158,15 @@ modifier introduce control over the execution *context*. ```ascii Crossing Call (Realm A calls Realm B's crossing function): - [Realm A Context] --cross()--> [Realm B Context]----------+ - | | - | Executes Realm B's code | + [Realm A Context] --cross()--> [Realm B Context]-----------+ + | | + | Executes Realm B's code | | (within Realm B's context)| - | Can modify Realm B State | - | | + | Can modify Realm B State | + | | [Realm A State] <----return----+- std.CurrentRealm() is B -+ - | | - +--------------------------+ + | | + +---------------------------+ ``` A common question is: What if Realm A crosses into Realm B, and then Realm B