DIP: 0002 Title: Special Transactions Author: Samuel Westrich, Alexander Block, Andy Freer Comments-Summary: No comments yet. Status: Final Type: Standard Created: 2018-04-30 License: MIT License
This DIP adds a basis for new transaction types that will provide on-chain metadata to assist various consensus mechanisms. This will allow for a more native way to implement new features which don’t naturally fit into the current concept of transactions.
Currently, new features and consensus mechanisms have to be implemented on top of the restrictions imposed by the simple nature of transactions. Since classical transactions can only carry inputs and outputs, they are most useful for financial transactions (i.e. transfers of quantities of Dash between addresses on the distributed ledger). These inputs and outputs carry scripts and signatures which are used to authorize and validate the transaction.
To implement new on-chain features and consensus mechanisms which do not fit into this concept of financial transactions, it is often necessary to misuse the inputs/outputs and their corresponding scripts to add additional data and meaning to a transaction. For example, new opcodes would have to be introduced to mark a transaction as something special and add a payload. In other cases, OP_RETURN
has been misused to store data on-chain.
This method of implementing new features results in some verification and consistency complications that can only be resolved with complicated, error-prone code. It also requires all parts of the ecosystem to reimplement the verification and consistency checks for each new feature.
Dash has so far avoided such extensions and misuse of the transaction format, but upcoming features would make this unavoidable. Instead of misusing the inputs/outputs of the transaction for every new feature or consensus mechanism, this DIP introduces a solution to provide a reusable framework for such extensions. This framework, called “Special Transactions”, updates and expands classical transactions with an additional type (a meaning) and an additional payload.
This DIP increments the transaction version to 3 and splits the field into two 16-bit fields with the second field now becoming transaction type. A classical transaction will be of transaction type 0 to remain backwards compatible.
A non-zero type indicates a special transaction with an extra payload appended after the last of the classical transaction fields. The internal structure of the payload is specific to the special transaction type. A newly introduced special transaction type should clearly define the structure of the payload so that it can be safely serialized, deserialized and verified. The individual new special transaction types will be defined by new DIPs and are not subject to this DIP.
The inputs and outputs of special transactions usually have the same meaning as with classical transactions. Verification and processing of these does not change for most special transaction types. If exceptions are made to this rule, a new DIP describing the changes in detail and a deployment plan must be provided.
The new transaction format is defined as follows:
Bytes | Name | Data Type | Description |
---|---|---|---|
2 | version | uint16_t | Transaction version number; currently version 2. Programs creating transactions using newer consensus rules may use higher version numbers. |
2 | type | uint16_t | Type for a classical transaction will be 0. View transaction types for more information. |
Varies | tx_in count | compactSize uint | Number of inputs in this transaction. |
Varies | tx_in | txIn | Transaction inputs. |
Varies | tx_out count | compactSize uint | Number of outputs in this transaction. |
Varies | tx_out | txOut | Transaction outputs. |
4 | lock_time | uint32_t | A time (Unix epoch time) or block number. |
1-9 | extra_payload size | compactSize uint | Variable number of bytes of extra payload. |
Varies | extra_payload | blob | Extra payload will be appended based on the transaction type. |
While implementing special transactions, implementors might choose to extend existing transaction classes by adding the payload fields to these classes. However, it is important to keep backwards compatibility when serializing, hashing or signing instances of these classes. This means that any classical transaction (type = 0, regardless of version) should NOT include these new fields while serializing, hashing or signing. A serialized classical transaction must always be identical to a transaction serialized by a program or library which does not support special transactions. The same applies to hashing and signing of classical transactions.
For special transactions, the extra_payload_size
and extra_payload
fields must be included when serialized, deserialized or hashed.
All OP-Codes which perform any signing/verification (e.g. CHECKSIGVERIFY) must also include both fields when calculating the signed hash.
This ensures that payloads can’t be modified after a transaction has been signed.
The introduction of special transactions will require the whole Dash ecosystem to perform a one-time mandatory update of all the software and libraries involved.
Software and libraries will have to be changed so that they can differentiate between classical transactions and special transactions. Deserialization of a classical transaction remains unchanged. Deserialization of a special transaction requires the software/library to at least implement skipping and ignoring the extra_payload field. Validation and processing of the inputs and outputs of a special transaction must remain identical to classical transactions.
A classical transaction can be identified by the 16-bit type field being 0. Please note that if the the 16-bit type field is 0, both 16-bit fields can also be interpreted as a single 32-bit field which would equal the value in the 16-bit version field. This is to allow some backwards compatibility for software/libraries which do not implement special transactions. However, this backwards compatibility is limited and will fail when special transactions are encountered.
A special transaction can be identified by the 16-bit version field being >= 3 and the 16-bit type field being non-zero.
The idea is to minimize the work necessary for future network wide upgrades. Only the initial introduction of special transactions will require more work. After that, the software and library implementers will determine if and when they want to implement newly introduced special transaction types. Clients that, for example, are only interested in following the financial ledger can completely ignore new special transactions as long as they correctly process the inputs and outputs of these special transactions. Only clients that are interested in Dash’s advanced features would need to selectively implement new special transaction types.
Copyright (c) 2018 Dash Core Group, Inc. Licensed under the MIT License