-
Notifications
You must be signed in to change notification settings - Fork 363
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
protocol/state: replace Outpoint with OutputID
**Problem** Outpoint is a variable-length structure `<txid>:<index>` which is 33-40 bytes long (33 bytes for most transactions). It is used by transaction inputs to identify exact output in the UTXO set ("Assets Merkle Tree"). The tree leafs contain `SHA3(output)` which allows save space and requires transactions to carry redundant copies of spent outputs to perform validation (otherwise nodes would have to store the entire outputs instead of their hashes — over 2x more data, and the ratio is much bigger in protocol 2). Also, for HSM-friendliness the TXSIGHASH must contain a redundant output's hash: `SHA3(txid || input index || SHA3(output))`. **Solution:** We define two new terms: * `OutputID = SHA3(TxHash || OutputIndex)` * `UnspentID = SHA3(OutputID || SHA3(OutputCommitment))` How are these used: 1. Transaction input contains **OutputID** to identify the output being spent. This is a unique identifier of the output. 2. Transaction input uses **second serialization flag** to indicate if it contains the entire previous Output Commitment, or its hash (instead of empty place). 3. UTXO set becomes a **proper set** containing **UnspentIDs** instead of `{Outpoint -> SHA3(OutputCommitment)}`. When a node validates a transaction, it computes `UnspentID` using provided `OutputID` and previous `OutputCommitment`. If the given unspent ID is present in the UTXO set, then previous output is proved to be both authentic and available for spending. **Upsides:** 1. The outputID is constant-size and shorter: 32 bytes instead of 33-40 bytes. This simplifies merkle tree design, transaction data structure and all pieces of software that need to handle outpoints. 2. All outputs (via unspentIDs) in the transaction are randomized across the Assets Merkle Tree instead of being crammed inside a common subpath `<txid>||...`. 3. Inputs automatically commit directly to the spent outputs, so TXSIGHASH does not need to do that and can be simplified to `SHA3(txid || input index)`. HSM is able to verify which output this input commits to without having access to the entire parent transaction. 4. We keep the term _outpoint_ to mean a pair `(txid, index)`, but is internal to Chain Core to support random access to UTXOs. Validation protocol no longer uses outpoints. 5. UTXO takes 2x less RAM because it only contains unpent IDs (32 bytes) instead of a key-value pair (64+ bytes). 6. When we get to _tx entries_ design, we'll generalize the idea of OutputID to EntryID, so that any entry can have a unique identifier. **Downsides:** 1. OutputID no longer indicates the transaction ID which makes it impossible to navigate the chain of transactions without also having a mapping `outpoint -> txid:index`. UTXO tree is not enough as it's only reflecting the latest state of the chain and throws away spent outpoints. Note that in order to navigate the transactions in practice one still needs the mapping `txid -> tx`, so maintaining one more index might not be a significant increase in complexity. Chain is doing this indexing already and we keep that mapping. 2. Chain Core no longer returns (txid,position) pair for annotated txinputs (called `spent_output:{transaction_id:String,position:Int}`), but instead returns output_id (`spent_output_id:String`). To maintain full compatibility, we'd need to make an additional request to locate the previous output's txid and position, but I'm not sure any application actually relies on such historical data. For spending (locating unspents), we fully maintain compatibility with clients using (txid,position) pairs. This is a part of a package of breaking changes in P1: #239 See previous reviews: #417 Closes #421
- Loading branch information
Showing
57 changed files
with
564 additions
and
431 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.