To implement transient storage (tstorage
) in the FVM, allowing data to persist within the scope of a single transaction and accessible across multiple calls within that transaction. This data should reset automatically at the end of each transaction.
At the level where memory tracking occurs for EVM actor execution, we find the System
struct:
/// Platform Abstraction Layer bridging the FVM to EVM
pub struct System<'r, RT: Runtime> {
pub rt: &'r RT,
/// Current bytecode (blake2b256(ipld_raw(bytecode)), keccak256(bytecode))
bytecode: Option<EvmBytecode>,
/// EVM storage slots for contract state
slots: StateKamt<RT::Blockstore>,
/// Contract's nonce (incremented for new actors)
pub(crate) nonce: u64,
/// Last saved state root. None if the current state hasn’t been saved yet.
saved_state_root: Option<Cid>,
/// Read-only (staticcall) context
pub readonly: bool,
/// Chain randomness from the current epoch
randomness: Option<[u8; 32]>,
/// If the actor is a "zombie" (selfdestructed but still executing)
pub(crate) tombstone: Option<Tombstone>,
}
To implement tstorage
, we propose adding a field for transient_storage
:
/// Transient storage, flushed at the end of each message execution
transient_storage: TransientStorage,
The TransientStorage
struct can mirror Memory
(in actors/evm/src/interpreter/memory.rs
), adapted for transaction-scoped data that persists across function calls in the same transaction but is cleared afterward.
transient_storage
should be accessible throughout a high-level transaction call, including during nested calls (delegatecall
, call
, create
).transient_storage
should only persist within a single transaction. This means it is cleared at the end of the transaction and does not carry over to future transactions.delegatecall
, call
, and create
operations, should have read/write access to the same transient data in transient_storage
.A concern with placing transient_storage
in System
is that the System
object may be instantiated multiple times within a single transaction. For example, if a contract deploys a new contract within the same transaction, each contract could get its own System
instance, leading to separate transient_storage
instances. This would disrupt the goal of having a single shared transient storage for the entire transaction context.
If System
is indeed instantiated multiple times within a transaction, then System
may not be the appropriate layer for TransientStorage
. Instead, we may need a higher-level context or transaction manager to ensure transient_storage
persists consistently across nested calls and contract creations within the transaction.
transient_storage: TransientStorage
to System
, implemented similarly to Memory
but scoped to transaction data.transient_storage
is available across nested calls and persists only for the transaction duration.System
is instantiated multiple times within a transaction to determine if it’s the right place for transient_storage
.