Adding SIGHASH to TXID

Adding SIGHASH to TXID
2022-05-07 11:55 ` Jeremy Rubin
  
From: vjudeu @ 2022-05-07  4:50 UTC (permalink / raw)
  To: bitcoin-dev

For now, we have txid:vout as a previous transaction output. This means that to have a stable TXID, we are forced to use SIGHASH_ALL somewhere, just to prevent any transaction modifications that can happen during adding some inputs and outputs. But it seems that new sighashes could be far more powerful than we expected: it is technically possible to not only remove previous transaction output by using SIGHASH_ANYPREVOUT. We can do more and do it better, we could decide, how to calculate this txid at all!

So, something like SIGHASH_PREVOUT_NONE would be similar to SIGHASH_NONE (applied to the previous transaction, taken from txid). To have SIGHASH_ANYPREVOUT, we need to remove absolutely everything, I don't know any such sighashes, because even SIGHASH_NONE | SIGHASH_ANYONECANPAY will commit at least to some fields, for example to the locktime. But, if we introduce SIGHASH_PREVOUT_XYZ flags for all existing sighashes, we would have this:

SIGHASH_PREVOUT_NONE
SIGHASH_PREVOUT_SINGLE
SIGHASH_PREVOUT_ALL
SIGHASH_PREVOUT_ANYONECANPAY

Then, the procedure is as follows: we use txid:vout to find our previous transaction. Then, we apply those sighashes to this previous transaction, to form a new txid, that will be checked during every OP_CHECKSIG-based opcode. In this way, our txid:vout is used just to do transaction lookup, after that, sighashes can be applied to the previous transaction, so our txid could remain stable, even if someone will add some inputs and outputs.

By default, we could use SIGHASH_PREVOUT_ALL, that would mean our txid:vout remains unchanged. Then, SIGHASH_PREVOUT_SINGLE would obviously mean, that we want to commit only to this particular previous transaction output. That would allow adding any new outputs to the previous transaction, without affecting our replaced txid, but also without blindly accepting any txid, because some data of the previous transaction would be still hashed.

Then, SIGHASH_PREVOUT_NONE is an interesting case, because it would mean that no outputs of the previous transaction are checked. But still, the inputs will be! That would mean: "I don't care about in-between addresses, but I care that it was initiated from these inputs". In this case, it is possible to choose some input without those flags, and then apply SIGHASH_PREVOUT_NONE many times, to make sure that everything started from that input, but everything in-between can be anything.

All of those three SIGHASH_PREVOUT_XYZ flags could be combined with SIGHASH_PREVOUT_ANYONECANPAY. That would mean all inputs of the previous transaction are discarded, except from the input number matching "vout". Or we could just use SIGHASH_PREVOUT_ANY instead and discard all inputs from that previous transaction, that could also be combined with other sighashes.

So, to sum up, by applying sighashes to the previous transaction, instead of allowing for any transaction, we could still have some control of our txid, and I think it could be better than just saying "give me any txid, I will accept that". I think in most cases we don't want to allow any txid: we want to only "control the flow", just to make sure that our signatures will sign what we want and will not be invalidated by changing some transaction inputs and outputs, unrelated to the currently-checked signature.


 permalink raw reply	[|nested]
2022-05-07  4:50 [bitcoin-dev] Adding SIGHASH to TXID vjudeu

  2022-07-03  5:45   ` vjudeu
  
From: Jeremy Rubin @ 2022-05-07 11:55 UTC ( / )
  To: vjudeu, Bitcoin Protocol Discussion



Have you seen the inherited ID proposal from John Law on this list?

It's a pretty thorough treatment of this type of proposal, curious if you
think it overlaps what you had in mind?

Honestly, I've yet to fully load in exactly how the applications of it
work, but I'd be interested to hear your thoughts.

On Sat, May 7, 2022, 4:55 AM vjudeu via bitcoin-dev <
bitcoin-dev@lists•linuxfoundation.org> wrote:

> For now, we have txid:vout as a previous transaction output. This means
> that to have a stable TXID, we are forced to use SIGHASH_ALL somewhere,
> just to prevent any transaction modifications that can happen during adding
> some inputs and outputs. But it seems that new sighashes could be far more
> powerful than we expected: it is technically possible to not only remove
> previous transaction output by using SIGHASH_ANYPREVOUT. We can do more and
> do it better, we could decide, how to calculate this txid at all!
>
> So, something like SIGHASH_PREVOUT_NONE would be similar to SIGHASH_NONE
> (applied to the previous transaction, taken from txid). To have
> SIGHASH_ANYPREVOUT, we need to remove absolutely everything, I don't know
> any such sighashes, because even SIGHASH_NONE | SIGHASH_ANYONECANPAY will
> commit at least to some fields, for example to the locktime. But, if we
> introduce SIGHASH_PREVOUT_XYZ flags for all existing sighashes, we would
> have this:
>
> SIGHASH_PREVOUT_NONE
> SIGHASH_PREVOUT_SINGLE
> SIGHASH_PREVOUT_ALL
> SIGHASH_PREVOUT_ANYONECANPAY
>
> Then, the procedure is as follows: we use txid:vout to find our previous
> transaction. Then, we apply those sighashes to this previous transaction,
> to form a new txid, that will be checked during every OP_CHECKSIG-based
> opcode. In this way, our txid:vout is used just to do transaction lookup,
> after that, sighashes can be applied to the previous transaction, so our
> txid could remain stable, even if someone will add some inputs and outputs.
>
> By default, we could use SIGHASH_PREVOUT_ALL, that would mean our
> txid:vout remains unchanged. Then, SIGHASH_PREVOUT_SINGLE would obviously
> mean, that we want to commit only to this particular previous transaction
> output. That would allow adding any new outputs to the previous
> transaction, without affecting our replaced txid, but also without blindly
> accepting any txid, because some data of the previous transaction would be
> still hashed.
>
> Then, SIGHASH_PREVOUT_NONE is an interesting case, because it would mean
> that no outputs of the previous transaction are checked. But still, the
> inputs will be! That would mean: "I don't care about in-between addresses,
> but I care that it was initiated from these inputs". In this case, it is
> possible to choose some input without those flags, and then apply
> SIGHASH_PREVOUT_NONE many times, to make sure that everything started from
> that input, but everything in-between can be anything.
>
> All of those three SIGHASH_PREVOUT_XYZ flags could be combined with
> SIGHASH_PREVOUT_ANYONECANPAY. That would mean all inputs of the previous
> transaction are discarded, except from the input number matching "vout". Or
> we could just use SIGHASH_PREVOUT_ANY instead and discard all inputs from
> that previous transaction, that could also be combined with other sighashes.
>
> So, to sum up, by applying sighashes to the previous transaction, instead
> of allowing for any transaction, we could still have some control of our
> txid, and I think it could be better than just saying "give me any txid, I
> will accept that". I think in most cases we don't want to allow any txid:
> we want to only "control the flow", just to make sure that our signatures
> will sign what we want and will not be invalidated by changing some
> transaction inputs and outputs, unrelated to the currently-checked
> signature.
> _______________________________________________
> bitcoin-dev mailing list
> bitcoin-dev@lists•linuxfoundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>
2022-05-07 11:55 ` Jeremy Rubin

  
From: vjudeu @ 2022-07-03  5:45 UTC (permalink / raw)
  To: Jeremy Rubin, Bitcoin Protocol Discussion

> Have you seen the inherited ID proposal from John Law on this list?

I didn't see that before posting, I'm still trying to get more familiar with that (and with proposals, where every single field in each transaction is controlled for inclusion or exclusion).

> Honestly, I've yet to fully load in exactly how the applications of it work, but I'd be interested to hear your thoughts.

The main use case is to control transaction flow. If you have everything signed with SIGHASH_ALL, then it is obvious that you can just use txid, and everything works. But on the other hand, if you use other sighashes, for example SIGHASH_SINGLE|SIGHASH_ANYONECANPAY, then you should be able to make a new transaction spending your signed output, no matter which inputs and outputs will be added to the previous one. And that's why SIGHASH_PREVOUT_SOMETHING is needed, to control, which parts of the previous transaction are signed, and which are not. And to do that, it is needed to take the previous transaction, referenced by txid, and to modify it, based on provided SIGHASH_PREVOUT_SOMETHING sighashes.

To push things one step further, I think different sighashes should be proposed by default, that would make users more familiar with the whole concept of sighashes. Because now, the default behavior is to sign everything with SIGHASH_ALL. I think it should be changed, the Core client should propose different sighashes, based on created transaction, just to allow transaction joining. To start with, it could be just a simple checkbox "allow transaction joining", that would enable it, to see if it will be simple enough for most users.

SIGHASH_ANYONECANPAY - used for every input (because it allows fee bumping without changing signatures)
SIGHASH_SINGLE - used only when there is any corresponding output, and only when it has higher or equal amount than the corresponding input
SIGHASH_ALL - used when there is no corresponding output, or when the corresponding output is smaller, to prevent detaching it

In general, I think the transaction should be displayed like it is visible in many block explorers, and after clicking each input, users should see, what is signed, and what is not, so they should control sighashes in a similar user interface, as they use to choose coins. Inputs and outputs should be grayed or highlighted, based on sighashes selected by user, to allow understanding them better.


On 2022-05-07 13:55:48 user Jeremy Rubin <jeremy.l.rubin@gmail•com> wrote:
Have you seen the inherited ID proposal from John Law on this list?


It's a pretty thorough treatment of this type of proposal, curious if you think it overlaps what you had in mind?


Honestly, I've yet to fully load in exactly how the applications of it work, but I'd be interested to hear your thoughts.


On Sat, May 7, 2022, 4:55 AM vjudeu via bitcoin-dev <bitcoin-dev@lists•linuxfoundation.org> wrote:
For now, we have txid:vout as a previous transaction output. This means that to have a stable TXID, we are forced to use SIGHASH_ALL somewhere, just to prevent any transaction modifications that can happen during adding some inputs and outputs. But it seems that new sighashes could be far more powerful than we expected: it is technically possible to not only remove previous transaction output by using SIGHASH_ANYPREVOUT. We can do more and do it better, we could decide, how to calculate this txid at all!

So, something like SIGHASH_PREVOUT_NONE would be similar to SIGHASH_NONE (applied to the previous transaction, taken from txid). To have SIGHASH_ANYPREVOUT, we need to remove absolutely everything, I don't know any such sighashes, because even SIGHASH_NONE | SIGHASH_ANYONECANPAY will commit at least to some fields, for example to the locktime. But, if we introduce SIGHASH_PREVOUT_XYZ flags for all existing sighashes, we would have this:

SIGHASH_PREVOUT_NONE
SIGHASH_PREVOUT_SINGLE
SIGHASH_PREVOUT_ALL
SIGHASH_PREVOUT_ANYONECANPAY

Then, the procedure is as follows: we use txid:vout to find our previous transaction. Then, we apply those sighashes to this previous transaction, to form a new txid, that will be checked during every OP_CHECKSIG-based opcode. In this way, our txid:vout is used just to do transaction lookup, after that, sighashes can be applied to the previous transaction, so our txid could remain stable, even if someone will add some inputs and outputs.

By default, we could use SIGHASH_PREVOUT_ALL, that would mean our txid:vout remains unchanged. Then, SIGHASH_PREVOUT_SINGLE would obviously mean, that we want to commit only to this particular previous transaction output. That would allow adding any new outputs to the previous transaction, without affecting our replaced txid, but also without blindly accepting any txid, because some data of the previous transaction would be still hashed.

Then, SIGHASH_PREVOUT_NONE is an interesting case, because it would mean that no outputs of the previous transaction are checked. But still, the inputs will be! That would mean: "I don't care about in-between addresses, but I care that it was initiated from these inputs". In this case, it is possible to choose some input without those flags, and then apply SIGHASH_PREVOUT_NONE many times, to make sure that everything started from that input, but everything in-between can be anything.

All of those three SIGHASH_PREVOUT_XYZ flags could be combined with SIGHASH_PREVOUT_ANYONECANPAY. That would mean all inputs of the previous transaction are discarded, except from the input number matching "vout". Or we could just use SIGHASH_PREVOUT_ANY instead and discard all inputs from that previous transaction, that could also be combined with other sighashes.

So, to sum up, by applying sighashes to the previous transaction, instead of allowing for any transaction, we could still have some control of our txid, and I think it could be better than just saying "give me any txid, I will accept that". I think in most cases we don't want to allow any txid: we want to only "control the flow", just to make sure that our signatures will sign what we want and will not be invalidated by changing some transaction inputs and outputs, unrelated to the currently-checked signature.
_______________________________________________
bitcoin-dev mailing list
bitcoin-dev@lists•linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev


 permalink raw reply	[|nested]