Moving the creation of split tickets from on-chain to off-chain has the benefit of decreasing the footprint of these tickets in the blockchain, with all the associated benefits this brings.
Assuming the previous changes to allow the safe creation and redeeming of such tickets are accepted, we can consider other changes to the layout of ticket transactions to simplify it further and fix the problem of Politeia voting rights being dependent on a regular P2PKH address being stored in the largest commitment address.
For a quick review on the current layout of ticket transactions, see my previous post on the challenges of split tickets.
What follows is a basic exposition on what I feel are the most useful changes.
Outline of Changes
- Modify the StakeCommitment (odd-numbered outputs) of ticket transactions;
- Instead of using an
OP_RETURN
as the first byte of the pkscript, they now use a newOP_SSTXCOMMITMENT
opcode;
- Instead of using an
- Add a new StakeProposalVoteAddress output;
- They carry a 0 value;
- They have a standard p2pkh address, tagged with a (new)
OP_SSTXPROPVOTEADDR
opcode; - Tickets may have only one output with such tag;
- Drop the requirement that len(outputs) == len(inputs)*2 + 1;
- Output semantics are controlled solely by the special stake opcodes at the start of each output script instead also relying on the output’s index in the transaction;
- Drop the requirement that the value of each input must be equal to the commitment amount of each respective output;
- This enables creation of both fan-in and fan-out ticket transactions (eg: 5 inputs generating a single ticket commitment or one input generating multiple commitments);
- Modify the StakeChange Outputs (the > 0, even-numbered outputs) to be optional;
Rationale
Most of the proposed modifications naturally arise from the central one: change the requirement that the number of ticket inputs equal twice the number of outputs plus one (the ticket submission output).
Maintaining this restriction is unnecessary when solo voting or when using a voting service provider: the wallet creating the ticket transaction can ensure whatever division it wants and voting pools still using the on-chain fees system can check if a commitment is present, independently of the originating inputs.
And when performing a split ticket purchase, however way the ticket is created (either the existing on-chain split ticket matcher service in use or the proposed LN service) participants can ensure that their respective commitment script and amount are correct before signing their inputs into the ticket using a SIGHASHALL signature, permanently committing to the transaction outputs.
Once this restriction is dropped and inputs can be used to fund the ticket at will, new possibilities for building the ticket arise: a solo or pool voting wallet can drop the use of a split transaction and fund the ticket directly by spending all its UTXOs and using only a single return commitment and change address (reducing the overall size of the involved transactions and fees paid to miners). Split tickets could also be funded directly by users with many UTXOs without a consolidating transaction first.
The next sessions will provide a rough outline for each change. We note that the level of detail presented is not yet sufficient to implement directly and will require a detailed DCP before implementation begins anyway, but it should be sufficient to convey the general direction intended.
Changes to the Stake Commitment Output
We introduce a new opcode, OP_SSTXCOMMITMENT
and use that opcode in replacement of the initial OP_RETURN
to identify commitment outputs for the ticket.
This allows commitment output scripts to be identified “locally”, without having to look at the container transaction details.
It also allows hardware wallets to identify, decode and display the outputs when checking them individually without having to pass down further transaction state (which is useful in some scenarios of streamed confirmation/signing).
The new StakeProposalVoteAddress
This output is intended to identify the address used for Politeia voting. Currently, the largest commitment address is the one selected for voting. However, that is not usually desired in the presence of split tickets as it allows for influence amplification of proposal voting power.
Even in solo voting situations, the ticket buyer might want to use a separate wallet for proposal voting for privacy or accessibility reasons. For example, solo voters might be using a separate cold wallet to fund tickets but may elect to use a hot wallet to hold their Politeia voting keys for easier proposal voting.
Therefore we introduce a new (optional) output in ticket transactions. This output follows the same convention established for change outputs: a special tag opcode (tentatively identified as OP_SSTXPROPVOTEADDR) followed by a standard Pay to PubKey Hash (or the Alt-Hash variant).
Output Count and Amount Correspondence Changes
One annoying feature of current ticket transactions is requiring a number of outputs equal to two times the number of inputs, plus the submission output. For each input, one corresponding commitment and one change output must be present.
However, due to the use of split transactions, the enormous majority of tickets do not carry a change mount, opting to use an empty change address and zero value in those outputs, which is extremely wasteful of space and bandwidth.
There’s also little point in requiring via consensus rules that the commitment amounts match a corresponding input amount:
- In solo voting setups, the ticket buyer and voter is the same entity and use a single output, therefore no correspondence is needed;
- In VSP voting setups, the pool needs to ensure that one of the commitment amounts is of the minimum required fee amount and pays to one of the pool’s subsidy addresses. However, it is not important to ensure that amount corresponds to any input amount, since all funds are coming from a single entity purchasing the ticket;
- In on-chain split ticket setups, each participant needs to ensure their commitment amount and address is present in the ticket before signing their corresponding input. Consensus rules when signing using a SIGHASHALL signature type already guarantee that no malleability is possible in the output once signed, therefore services that build the ticket interactively don’t need to guarantee correspondence: only that each individual participant agrees to the proposed ticket layout;
- In off-chain split ticket setups the amounts are not directly tracked in the ticket purchase itself and therefore the ticket ends up being similar to a solo ticket.
Do note that consensus rules need to ensure that the sum of commitment amounts equal the total input amount to allow correct split of the vote reward. However this proposal intends to remove the requirement that the corresponding values be equal.
This opens up the possibility of having both fan-in (multiple inputs, single output) and fan-out (single input, multiple outputs) scenarios.
Fan-ins could be used by single voters that wish to purchase a ticket using multiple funding outputs but little (or no) change (and can accept the locking of funds implied by usage of an SSTXChange output). A smart procedure for searching for funding utxos for a ticket might also take that into account, reducing the overall network usage by dropping the need for split transactions entirely.
Fan-outs are useful in on-chain split ticket scenarios, where a single input with a multi (or possibly Schnorr) signature could be arranged such that the ticket can only be purchase with the cooperation of all participants. This would mitigate some of the possible problems that having inputs individually controllable by participants introduce.
More Exotic Changes
A few more exotic changes to the staking system might be considered for inclusion in this set of consensus changes. These are proposed here as a way to gather current sentiment regarding all stake-related changes, but they might be subject to separate discussion, implementation and voting.
Also their actual status as something wanted or needed at all is debatable, so these should be considered more as “shower thoughts”.
Use Amount in Commitment Outputs
Instead of encoding the amount inside the pkscript of ticket transactions, the amount could be encoded directly in the amount field of the output. This would further reduce the size of ticket transactions (by allowing the use of an existing field that is currently always zero) and would open up the possibility for changing the semantics of how the ticket price (stake difficulty) is encoded in a ticket.
This would lead to a significant change in consensus rules, specifically related to management of the UTXO set, since a nodes would no longer be able to rely in the fact that the amount of an output is different than zero to include it in the set.
Change Ticket Difficulty Encoding in SSTX
Given the previous change, it would be possible to then encode the ticket price as the sum of the amounts of the individual commitments, instead of using a single stake submission output for this purpose.
This would maintain the invariant that the sum of outputs of a transaction be less than the sum of inputs, which is desirable.
Encode a Single Fee Allowance or Drop It
Instead of encoding a fee allowance limit for each commitment, this value could be encoded inside a single script (for example, on a specific output of the ticket).
One way to do this would be to combine this change with the previous ones and encode the limits inside the ticket submission output. These same limits would then be enforced on all outputs when deciding on how to pay revocation fees.
Another alternative is to drop the fee allowance altogether. If we move the Decred ecosystem to paying for pool fees via LN, then the fee allowance becomes redundant and we can simply enforce that fees in revocations cannot exceed some given multiple of the standard relay fee or they must use a fee rate comparable (within some percentage margin) to the fee used to purchase the ticket.
Fractional Politeia Voting Power
This isn’t strictly a change to the ticket layout, but assuming off-chain shared tickets become widespread it might be interesting to consider changing Politeia to use fractional (weighted) voting versus a single voting key.
One possible way to make this work would be to use another group key as a Politeia voting key and then get this group key to pre-register the voting percentages for the individuals keys.
This message can be assembled during the initial ticket construction and sent by any participant once the ticket has matured.
Then Politeia could either aggregate the fractional votes (weighted by their participation percentage) or perform a (weighed) deterministic lottery to choose which one of the keys in the group gets to cast the vote for each proposal.
Final Discussion
These changes remove some of the cruft that has accumulated in ticket transactions and that are pretty much unneeded given how they are currently used in the network and how the proposal to use LN to fund split tickets works.
Their implementation would require quite a lot of concerted effort in the node and wallet codebases to be able to handle the new structure. However the benefits in reduced footprint for the blockchain on a longer timeframe are significant enough that we should seriously consider starting the work towards doing this.
The next (and final) post in this series will provide a summary of the full set of changes needed to implement split ticket purchasing via LN.