From f8da2347d9cf25e2d82a2e6e354b6599ae3ce55a Mon Sep 17 00:00:00 2001 From: Siddharth Suresh Date: Thu, 16 Jan 2025 09:18:25 -0800 Subject: [PATCH] CAP-0067 - Emit events at the operation layer (#1619) * CAP-0067 - Emit events at the operation layer * update --- core/cap-0067.md | 89 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 79 insertions(+), 10 deletions(-) diff --git a/core/cap-0067.md b/core/cap-0067.md index bafde198a..620296f8a 100644 --- a/core/cap-0067.md +++ b/core/cap-0067.md @@ -68,19 +68,65 @@ index 5113005..ee10e20 100644 %struct SCVal; diff --git a/Stellar-ledger.x b/Stellar-ledger.x -index 6ab63fb..80a2635 100644 +index 6ab63fb..e99304e 100644 --- a/Stellar-ledger.x +++ b/Stellar-ledger.x -@@ -447,6 +447,7 @@ struct TransactionMetaV3 +@@ -446,7 +446,44 @@ struct TransactionMetaV3 + // Soroban transactions). }; ++struct OperationMetaV2 ++{ ++ // We can use this to add more fields, or because it ++ // is first, to change OperationMetaV2 into a union. ++ ExtensionPoint ext; ++ ++ LedgerEntryChanges changes; ++ ++ ContractEvent events<>; ++ DiagnosticEvent diagnosticEvents<>; ++} ++ ++struct SorobanTransactionMetaV2 ++{ ++ SorobanTransactionMetaExt ext; ++ ++ SCVal returnValue; ++} ++ ++ ++struct TransactionMetaV4 ++{ ++ ExtensionPoint ext; ++ ++ LedgerEntryChanges txChangesBefore; // tx level changes before operations ++ // are applied if any ++ OperationMetaV2 operations<>; // meta for each operation ++ LedgerEntryChanges txChangesAfter; // tx level changes after operations are ++ // applied if any ++ SorobanTransactionMetaV2* sorobanMeta; // Soroban-specific meta (only for ++ // Soroban transactions). ++ ++ DiagnosticEvent txDiagnosticEvents<>; // Used for diagnostic information not tied ++ // to an operation. ++}; ++ // This is in Stellar-ledger.x to due to a circular dependency +// Only used before protocol 23 struct InvokeHostFunctionSuccessPreImage { SCVal returnValue; +@@ -465,6 +502,8 @@ case 2: + TransactionMetaV2 v2; + case 3: + TransactionMetaV3 v3; ++case 4: ++ TransactionMetaV4 v4; + }; + + // This struct groups together changes on a per transaction basis diff --git a/Stellar-transaction.x b/Stellar-transaction.x -index 6b10e4d..163430e 100644 +index 6b10e4d..adc42ee 100644 --- a/Stellar-transaction.x +++ b/Stellar-transaction.x @@ -1883,7 +1883,7 @@ enum InvokeHostFunctionResultCode @@ -92,21 +138,42 @@ index 6b10e4d..163430e 100644 case INVOKE_HOST_FUNCTION_MALFORMED: case INVOKE_HOST_FUNCTION_TRAPPED: case INVOKE_HOST_FUNCTION_RESOURCE_LIMIT_EXCEEDED: -@@ -2083,6 +2083,8 @@ struct InnerTransactionResult +@@ -2045,6 +2045,20 @@ enum TransactionResultCode + txSOROBAN_INVALID = -17 // soroban-specific preconditions were not met + }; + ++struct TransactionResultExtensionV1 ++{ ++ // Stores a hash per operation ++ Hash eventsHash<>; ++ ++ union switch (int v) ++ { ++ case 0: ++ void; ++ } ++ ext; ++}; ++ ++ + // InnerTransactionResult must be binary compatible with TransactionResult + // because it is be used to represent the result of a Transaction. + struct InnerTransactionResult +@@ -2083,6 +2097,8 @@ struct InnerTransactionResult { case 0: void; + case 1: -+ Hash eventsHash; ++ TransactionResultExtensionV1 v1; } ext; }; -@@ -2130,6 +2132,8 @@ struct TransactionResult +@@ -2130,6 +2146,8 @@ struct TransactionResult { case 0: void; + case 1: -+ Hash eventsHash; ++ TransactionResultExtensionV1 v1; } ext; }; @@ -131,7 +198,7 @@ contract: asset, topics: ["clawback", from:Address, sep0011_asset:String], data: At the moment, if the issuer is the sender in a Stellar Asset Contract `transfer`, the asset will be minted. If the issuer is the recipient, the asset will be burned. The event emitted in both scenarios, however, is the `transfer` event. This CAP changes that behavior to instead emit the `mint`/`burn` event. ### New Events -This section will go over the semantics of how the additional `transfer` events are emitted for each operation, as well as the `fee` event emitted for the fee paid by the source account. These events will be emitted through the `events<>` field in `SorobanTransactionMeta`, and the SHA-256 hash of the events will be saved in the new `eventsHash` extension of `TransactionResult`. For consistency, the preimage of the hash stored in `InvokeHostFunctionResult` on success will just be the `returnValue` `SCVal`, and the events hash will be stored in `eventsHash` like any other transaction. +This section will go over the semantics of how the additional `transfer` events are emitted for each operation, as well as the `fee` event emitted for the fee paid by the source account. These events will be emitted through the `events<>` field in the new `OperationMetaV2`, and the SHA-256 hash of the events will be saved in `eventsHash<>` which is in the new `TransactionResultExtensionV1` extension of `TransactionResult`. For consistency, the preimage of the hash stored in `InvokeHostFunctionResult` on success will just be the `returnValue` `SCVal`, and the events hash will be stored in `eventsHash` like any other transaction. Soroban events will also be emitted through `OperationMetaV2`. Note that the `contract` field for these events corresponds to the Stellar Asset Contract address for the respective asset. Note that the Stellar Asset Contract instance is not required to be deployed for the asset. The events will be published using the reserved contract address regardless of deployment status. @@ -318,9 +385,11 @@ contract: asset, topics: ["transfer", from:Address, to:Address, sep0011_asset:St The admin isn't relevant information when a mint or `clawback` occurs, and it hinders compatibility with SEP-41 for when these two events are added to it because the admin is an implementation detail. For a custom token, an admin doesn't need to be a single `Address`, or an admin may not required at all to emit either event. -### No change to TransactionMeta XDR +### TransactionMetaV4 + +This CAP introduces a new `TransactionMeta` version, `TransactionMetaV4`. Now that we're emitting events for more than just Soroban, this allows us to clean up the structure of meta because `TransactionMetaV3` assumed events would only be emitted for Soroban. This change also allows us to emit events at the operation layer instead of the transaction layer using the new `OperationMetaV2` type. -By using the existing `events<>` vector in `SorobanTransactionMeta`. We can avoid making any xdr changes. This does have some tradeoffs, mainly that all events for a given transaction will be emitted in a single vector, making it impossible to distinguish which operation emitted a specific event. The alternative would be to move Soroban meta from the transaction layer into the operation layer of transaction meta, but that would be a breaking change. +It's important to note that transaction meta is not part of the protocol, so the emission of `TransactionMetaV4` instead of `TransactionMetaV3` can be done using a config flag, allowing consumers of meta to switch on their own time. ### Emit the semantically correct event instead of no longer allowing the issuer to transfer due to missing a trustline