-
Notifications
You must be signed in to change notification settings - Fork 319
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CIP-0051? | Preserve submitter's ordering of transaction inputs #231
Changes from all commits
b2409a2
3cde608
227b98a
c929e3f
391264a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
--- | ||
CIP: ? | ||
Title: Preserve submitter's ordering of transaction inputs | ||
Authors: Gergely Szabo <gergely@mlabs.city> | ||
Discussions-To: | ||
Comments-Summary: | ||
Comments-URI: | ||
Status: Draft | ||
Type: Standards Track | ||
Created: 2022-02-25 | ||
License: Apache-2.0 | ||
--- | ||
|
||
# Preserve submitter's ordering of transaction inputs | ||
|
||
## Abstract | ||
|
||
This CIP proposes a way to improve efficiency of handling transaction inputs in Plutus scripts by changing the way they are representend in the ledger. | ||
|
||
## Motivation | ||
|
||
The current implementation of the transaction body stores transaction inputs as a set. When interacting with transaction inputs inside a validator script, this representation changes to a linked list, but the ordering of the transaction inputs is different than that of the originally submitted transaction's. In the case when we want to find a certain transaction input on chain, we need to do a costly filtering on the input list with the worst case of O(n). | ||
However if the transaction inputs would be stored as an array, preserving the original ordering, we could better optimise our scripts by determining the order of inputs off-chain and simplifying the search to a pattern match. | ||
For example, for a script needing transaction inputs for two purposes: one for updating the datum of the script, and one or more for supplying the funds. We could order these inputs such that the one including the datum comes first, and then we can use a pattern match `txWithDatum : txWithFunds = txInfoInputs`. | ||
|
||
## Specification | ||
|
||
In the CDDL definiotion of the transaction body, transaction inputs will need to be changed from Set to Array: | ||
|
||
``` | ||
transaction_body = | ||
{ 0 : [* transaction_input] ; inputs | ||
, 1 : [* transaction_output] | ||
, 2 : coin ; fee | ||
, ? 3 : uint ; time to live | ||
, ? 4 : [* certificate] | ||
, ? 5 : withdrawals | ||
, ? 6 : update | ||
, ? 7 : auxiliary_data_hash | ||
, ? 8 : uint ; validity interval start | ||
, ? 9 : mint | ||
, ? 11 : script_data_hash ; New | ||
, ? 13 : set<transaction_input> ; Collateral ; new | ||
, ? 14 : required_signers ; New | ||
, ? 15 : network_id ; New | ||
} | ||
``` | ||
|
||
Note that the Set is defined in the cardano-ledger specification as an Array of zero or more elements `set = [* a]`, so this would only cause a semantic change, without the actual change of the underlying data structure. | ||
|
||
## Rationale | ||
|
||
In theory we could pre-calculate the index of the searched transaction input off-chain, by relying on the ordering of transaction inputs (lexicographic ordering on `(TransactionID, TransactionIndex)`). But then, to pass this information to the script, we would need to use a redeemer, which could defeat the purpose of this optimisation with it's own fees. Also, we could only reliably do this after transaction balancing, but changing the transaction after balancing could affect fees, rendering the transaction unbalanced again. This method also introduces unnecessary complexity. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I am not sure that framing this as an optimization to save on fees is the best justification. Surely, it improves the developer experience and makes easier to work with transaction inputs. I think one of the most common problem with that is calculation of redeemer pointers and how it conflicts with transaction balancing (adding new inputs to cover for fee may invalid all existing pointers on inputs). If the argument is made about saving on fees, then it should come backed with numbers showing how much to help weigh whether the change is worth it or not. |
||
|
||
## Security considerations | ||
|
||
We considered the possibility of a man-in-the-middle attack, where the adversary could change the transaction input ordering, and altering the behaviour of a script. However the existing ledger rules for deriving txid are sufficient to guarantee the integrity of transactions, because the inputs (whether a set or a list) are included in the transaction body that gets hashed to a txid. Therefore, no changes would be required to txid derivation. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure to understand the point being made here and in particular, why transaction integrity is something that helps mitigating an adversary changing the order of inputs? |
||
|
||
## Backward Compatibility | ||
|
||
For ledger transactions before this CIP is implemented, the underlying CBOR data structure only changes semantically, and the difference between input order at submission and at script evaluation is irrelevant for the ledger. However, because scripts could rely on pattern matching by position, a new Plutus version is required. | ||
|
||
## Test Cases | ||
|
||
We need regression tests to assert that no utxo appears twice in the transaction input list. | ||
|
||
## Implementations | ||
|
||
The ledger implementation currently represents transaction inputs as a Map with the key of `(TransactionID, TransactionIndex)`. | ||
|
||
## Copyright | ||
|
||
This CIP is licensed under Apache-2.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.