Bitcoin Forum
May 05, 2024, 06:07:27 AM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1] 2 »  All
  Print  
Author Topic: SIGHASH precedence for multisig?  (Read 1472 times)
jl777 (OP)
Legendary
*
Offline Offline

Activity: 1176
Merit: 1132


View Profile WWW
March 02, 2016, 02:25:49 PM
Merited by ABCbits (1)
 #1

As you know there are several SIGHASH types, each signature has a byte at the end to indicate how it was signed.

I searched, but could not find any definitive explanation of the precedence and how all the various SIGHASH types affect each other.

For most inputs with a single signer, this is a moot issue, though even that doesnt seem to be true as some parts of an input appear to propagate to the entire tx, or its outputs or at least something beyond the apparent scope of the vin that is being signed.

But for a multisig output that is being signed by multiple signers and where the signers are using different SIGHASH types, I think there needs to be a defined way of figuring out what SIGHASH mode is in effect.

A few lines in the official docs leaves a lot to the imagination. Is it even valid for there to be different SIGHASH types in the same vin? Maybe it is just rejected if they dont all match? Or maybe there is an implicit precedence that applies?

James

http://www.digitalcatallaxy.com/report2015.html
100+ page annual report for SuperNET
1714889247
Hero Member
*
Offline Offline

Posts: 1714889247

View Profile Personal Message (Offline)

Ignore
1714889247
Reply with quote  #2

1714889247
Report to moderator
There are several different types of Bitcoin clients. The most secure are full nodes like Bitcoin Core, but full nodes are more resource-heavy, and they must do a lengthy initial syncing process. As a result, lightweight clients with somewhat less security are commonly used.
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction.
1714889247
Hero Member
*
Offline Offline

Posts: 1714889247

View Profile Personal Message (Offline)

Ignore
1714889247
Reply with quote  #2

1714889247
Report to moderator
1714889247
Hero Member
*
Offline Offline

Posts: 1714889247

View Profile Personal Message (Offline)

Ignore
1714889247
Reply with quote  #2

1714889247
Report to moderator
1714889247
Hero Member
*
Offline Offline

Posts: 1714889247

View Profile Personal Message (Offline)

Ignore
1714889247
Reply with quote  #2

1714889247
Report to moderator
TierNolan
Legendary
*
Offline Offline

Activity: 1232
Merit: 1083


View Profile
March 02, 2016, 02:54:57 PM
 #2

But for a multisig output that is being signed by multiple signers and where the signers are using different SIGHASH types, I think there needs to be a defined way of figuring out what SIGHASH mode is in effect.

From what I understand, the SIGHASH flag is used to determine what the signature actually signs.

transaction --- SIGHASH --->  signature-target --- ECDSA ---> Signature.

Since each signature has a different sighash byte, they can also use a different signature target.

There are only 2 steps.  The bottom 5 bits select one of the output options and the 6th bit selects if you want to blank out the other inputs.

Unless the bottom 5 bits are 0x02 (SIGHASH_NONE) or 0x03 (SIGHASH_SINGLE), all the outputs are included.  If the bit for 0x20 is set, then all inputs are blanked except the current input (SIGHASH_ANYONE_CAN_PAY).

See here.

While it could potentially be expanded, that would be a hard fork to include it in the basic script.  P2SH or SW could include new sighash operations in their script (and SW is expandable).

1LxbG5cKXzTwZg9mjL3gaRE835uNQEteWF
jl777 (OP)
Legendary
*
Offline Offline

Activity: 1176
Merit: 1132


View Profile WWW
March 02, 2016, 03:25:15 PM
 #3

But for a multisig output that is being signed by multiple signers and where the signers are using different SIGHASH types, I think there needs to be a defined way of figuring out what SIGHASH mode is in effect.

From what I understand, the SIGHASH flag is used to determine what the signature actually signs.

transaction --- SIGHASH --->  signature-target --- ECDSA ---> Signature.

Since each signature has a different sighash byte, they can also use a different signature target.

There are only 2 steps.  The bottom 5 bits select one of the output options and the 6th bit selects if you want to blank out the other inputs.

Unless the bottom 5 bits are 0x02 (SIGHASH_NONE) or 0x03 (SIGHASH_SINGLE), all the outputs are included.  If the bit for 0x20 is set, then all inputs are blanked except the current input (SIGHASH_ANYONE_CAN_PAY).

See here.

While it could potentially be expanded, that would be a hard fork to include it in the basic script.  P2SH or SW could include new sighash operations in their script (and SW is expandable).
That is the part about how to make the modified tx to sign, but how do I treat a set of sigs for a tx where the different multisig signers use different SIGHASH modes?

I can verify it is a valid signature, but what happens if there is SIGHASH_ALL for one sig, SIGHASH_SINGLE for another and SIGHASH_ANYONE_CAN_PAY for the third sig for the same input. Things are complicated enough with the different vins for a tx, which might or might not be dependent on each other, but do I do an M of N and count any mismatched SIGHASH as invalid? and which ones are mismatched if there are three different ones? Maybe depending on other clues, it can be determined which SIGHASH mode is valid for a specific tx, but what if more than one could be valid? It seems there would need to be a precedence or at least much clearer explanation on what should happen in these mixed SIGHASH vins.

Then I can start to worry about what happens when we have a single tx that contains mixed SIGHASH vins. As it is, it is tempting to just require SIGHASH_ALL across the board.

James


http://www.digitalcatallaxy.com/report2015.html
100+ page annual report for SuperNET
TierNolan
Legendary
*
Offline Offline

Activity: 1232
Merit: 1083


View Profile
March 02, 2016, 03:56:22 PM
 #4

I can verify it is a valid signature, but what happens if there is SIGHASH_ALL for one sig, SIGHASH_SINGLE for another and SIGHASH_ANYONE_CAN_PAY for the third sig for the same input.

You compute the transaction for each signature separately.  You can't just work out the hash once, you have to do it for each of the signers (if they use different sighashes)

1LxbG5cKXzTwZg9mjL3gaRE835uNQEteWF
amaclin
Legendary
*
Offline Offline

Activity: 1260
Merit: 1019


View Profile
March 02, 2016, 04:04:02 PM
 #5

I can verify it is a valid signature, but what happens if there is SIGHASH_ALL for one sig, SIGHASH_SINGLE for another and SIGHASH_ANYONE_CAN_PAY for the third sig for the same input.
It is not a problem.
let me give you some pseudocode:

byte[] pubkey = getPubkey ( );
byte[] param = getSignaturePlusHashtype ( ); // signature concatenated with hash type
byte[] signature, int hashtype = param.split ( );   // get bare asn1 signature and 1-byte hashtype
byte[] digest;
switch ( hashtype )  
{
  case SIGHASH_ALL : digest = tx.createDigest ( all ); break;
  case SIGHASH_NONE: digest = tx.createDigest ( none ); break;  
}
verify ( signature, digest, pubkey )
jl777 (OP)
Legendary
*
Offline Offline

Activity: 1176
Merit: 1132


View Profile WWW
March 02, 2016, 04:07:27 PM
 #6

I can verify it is a valid signature, but what happens if there is SIGHASH_ALL for one sig, SIGHASH_SINGLE for another and SIGHASH_ANYONE_CAN_PAY for the third sig for the same input.

You compute the transaction for each signature separately.  You can't just work out the hash once, you have to do it for each of the signers (if they use different sighashes)
I understand this.

My question is AFTER it is validated, what does it mean?

Assume all the sigs verify. My understanding is that SIGHASH_SINGLE would affect things differently than SIGHASH_ALL, so with a valid SIGHASH_SINGLE and a valid SIGHASH_ALL mixed together in the same vin (from different multisig signers). Do I treat that input as a SIGHASH_SINGLE or SIGHHASH_ALL as it pertains to the side effects that go beyond the scope of vin itself. Or do I allocate half the funds as SIGHASH_ALL and half the funds as SIGHASH_SINGLE.

Do you see my problem?

For things like RBF where it has dominant precedence, the presence if it in any input makes the entire tx RBF enabled.

Similarily, if 1 of the N sigs is SIGHASH_xxx does SIGHASH_xxx dominate SIGHASH_yyy? And which is the xxx and yyy? Maybe its just a theoretical question and there arent any actual multisig tx with different SIGHASH types for the same vin, but unless the behavior is explicitly defined, would this create a split network unless all the bitcoin cores follow the same rules?

If the rules are so ambiguous and confusing (or missing), then it seems this could even be a current attack vector, unless all current nodes are following the identical rules. What are these rules?

James

http://www.digitalcatallaxy.com/report2015.html
100+ page annual report for SuperNET
jl777 (OP)
Legendary
*
Offline Offline

Activity: 1176
Merit: 1132


View Profile WWW
March 02, 2016, 04:08:19 PM
 #7

I can verify it is a valid signature, but what happens if there is SIGHASH_ALL for one sig, SIGHASH_SINGLE for another and SIGHASH_ANYONE_CAN_PAY for the third sig for the same input.
It is not a problem.
let me give you some pseudocode:

byte[] pubkey = getPubkey ( );
byte[] param = getSignaturePlusHashtype ( ); // signature concatenated with hash type
byte[] signature, int hashtype = param.split ( );   // get bare asn1 signature and 1-byte hashtype
byte[] digest;
switch ( hashtype )  
{
  case SIGHASH_ALL : digest = tx.createDigest ( all ); break;
  case SIGHASH_NONE: digest = tx.createDigest ( none ); break;  
}
verify ( signature, digest, pubkey )

Thanks you, but this is not the question. Assume the sigs verify. see above response

http://www.digitalcatallaxy.com/report2015.html
100+ page annual report for SuperNET
amaclin
Legendary
*
Offline Offline

Activity: 1260
Merit: 1019


View Profile
March 02, 2016, 04:14:35 PM
 #8

Thanks you, but this is not the question. Assume the sigs verify. see above response
Ok, verify ( signature, digest, pubkey ) method returns either 1 or 0
Note, that this method doesn't depend on any other variables. it does not know anything about satoshi sighash types.
The msig script m-of-n is valid if there are at least m hits of positive verifies
jl777 (OP)
Legendary
*
Offline Offline

Activity: 1176
Merit: 1132


View Profile WWW
March 02, 2016, 04:47:32 PM
 #9

Thanks you, but this is not the question. Assume the sigs verify. see above response
Ok, verify ( signature, digest, pubkey ) method returns either 1 or 0
Note, that this method doesn't depend on any other variables. it does not know anything about satoshi sighash types.
The msig script m-of-n is valid if there are at least m hits of positive verifies
And how to treat the x if the M sigs all use different sighash types?

My confusion is not about the actual signing or verifying step (of course I was quite confused about that till I got it working), but rather how to interpret the resulting signed tx.

A tx has multiple inputs and multiple outputs. But the inputs and outputs range from being totally indpendent to totally dependent and multiple sighash types within a single input seems to create a large number of implementations possible that all follow the rules and all end up with a different result.

It is the semantics of the different SIGHASH types that still confuse me. SIGHASH_ALL is thankfully used for majority and that is simple. The signature assumes everything is the same, no changes allowed. But the others do allow the tx to be changed. So what happens when we have M of N sigs, some that allow the tx to change and others that dont?

Maybe there is some actual documentation that describes things clearly?

Is the rule simply that if all the sigs verify for an input, we treat that input as verified fully? There is no possibility that a SIGHASH type that is different can invalidate the validity when it interacts with other SIGHASH types?

Like the SIGHASH_SINGLE, it appears to require a 1:1 correspondence of vins/vouts, but the different vins are independent. So if one msig signer uses SIGHASH_SINGLE and another uses SIGHASH_ALL, then the SIGHASH_SINGLE would be valid for more tx than the SIGHASH_ALL, so it makes sense that if the tx changes to invalidate the SIGHASH_ALL then the M of N is now M-1

I think that makes sense, but all combinations of SIGHASH modes needs to be well defined. I havent done the full matrix of possibilities yet, that is why I posted. I was hoping that such a thing was already thought through and documented

James

http://www.digitalcatallaxy.com/report2015.html
100+ page annual report for SuperNET
TierNolan
Legendary
*
Offline Offline

Activity: 1232
Merit: 1083


View Profile
March 02, 2016, 04:53:56 PM
 #10

My question is AFTER it is validated, what does it mean?

Signatures are pass/fail, they don't have meaning other than that.  SIGHASH_SINGLE means that you just sign the output that you are interested in.  You are saying "This signature is valid for any transaction which pays to this output".

Assume you had 2 inputs and 2 outputs and you are checking input zero.

The first signature is sighash_single & anyone_can_pay.  That means that you only include output zero.  The anyone can pay means that you also delete all the inputs, except the one you are signing (input zero).  Those inputs and outputs are the only ones that are involved in the signature.

The person who signed that signature signed any transaction with that input and that output.

That means you can add inputs and outputs and the transaction will remain valid (as long as that input and that output are in the same position).

The second signature is sighash_all.  That person signed the entire transaction.  If you change anything about the transaction, then it becomes invalid.

In theory, the first person could create a one input and one output transaction and sign it with (sighash_single | anyone_can_pay) and then sign it.  The second person can then take the transaction and modify it (adding the 2nd input and 2nd output) and then sign with sighash_all.  That 2nd signature is also valid, but only if there are no more changes.

1LxbG5cKXzTwZg9mjL3gaRE835uNQEteWF
jl777 (OP)
Legendary
*
Offline Offline

Activity: 1176
Merit: 1132


View Profile WWW
March 02, 2016, 05:01:31 PM
 #11

My question is AFTER it is validated, what does it mean?

Signatures are pass/fail, they don't have meaning other than that.  SIGHASH_SINGLE means that you just sign the output that you are interested in.  You are saying "This signature is valid for any transaction which pays to this output".

Assume you had 2 inputs and 2 outputs and you are checking input zero.

The first signature is sighash_single & anyone_can_pay.  That means that you only include output zero.  The anyone can pay means that you also delete all the inputs, except the one you are signing (input zero).  Those inputs and outputs are the only ones that are involved in the signature.

The person who signed that signature signed any transaction with that input and that output.

That means you can add inputs and outputs and the transaction will remain valid (as long as that input and that output are in the same position).

The second signature is sighash_all.  That person signed the entire transaction.  If you change anything about the transaction, then it becomes invalid.

In theory, the first person could create a one input and one output transaction and sign it with (sighash_single | anyone_can_pay) and then sign it.  The second person can then take the transaction and modify it (adding the 2nd input and 2nd output) and then sign with sighash_all.  That 2nd signature is also valid, but only if there are no more changes.
So unlike RBF enabled in one vin propagates to the entire tx, the signatures are always self contained regardless of how they are mixed. In a MofN multisig it is possible changing the tx will change the validity of some sigs, but as long as there are still M or more valid sigs, it is valid.

As long as there is no propagation beyond the current vin, I think it is ok. The RBF in any vin affecting all vins, just spooked me a bit and I wasnt sure about the local scope of SIGHASH. I guess I overcomplicated things.

Thanks

James

http://www.digitalcatallaxy.com/report2015.html
100+ page annual report for SuperNET
TierNolan
Legendary
*
Offline Offline

Activity: 1232
Merit: 1083


View Profile
March 02, 2016, 08:14:16 PM
 #12

So unlike RBF enabled in one vin propagates to the entire tx, the signatures are always self contained regardless of how they are mixed.

I think so, but it is probably worth checking a few transactions with mixes of signatures on testnet.

1LxbG5cKXzTwZg9mjL3gaRE835uNQEteWF
jl777 (OP)
Legendary
*
Offline Offline

Activity: 1176
Merit: 1132


View Profile WWW
March 02, 2016, 08:22:46 PM
 #13

So unlike RBF enabled in one vin propagates to the entire tx, the signatures are always self contained regardless of how they are mixed.

I think so, but it is probably worth checking a few transactions with mixes of signatures on testnet.
OK, so I am not crazy thinking this is a possible case of undefined behavior

I noticed it as I found my code was assuming only a single SIGHASH type per vin, but clearly there can be multiple signers.


http://www.digitalcatallaxy.com/report2015.html
100+ page annual report for SuperNET
TierNolan
Legendary
*
Offline Offline

Activity: 1232
Merit: 1083


View Profile
March 02, 2016, 10:42:01 PM
 #14

OK, so I am not crazy thinking this is a possible case of undefined behavior

Well, I would be 90% sure that the sighash applies on a per signature basis, but when in doubt, it is worth testing.

1LxbG5cKXzTwZg9mjL3gaRE835uNQEteWF
jl777 (OP)
Legendary
*
Offline Offline

Activity: 1176
Merit: 1132


View Profile WWW
March 02, 2016, 11:00:29 PM
 #15

OK, so I am not crazy thinking this is a possible case of undefined behavior

Well, I would be 90% sure that the sighash applies on a per signature basis, but when in doubt, it is worth testing.
I cant see a way that sighash isnt on a per sig basis as it is intimate part of the signing.

I think I was thinking about it a bit backwards, as the sigs are the endpoint of the process and not an intermediate that affects anything, other than if the vin is valid or not.

But actually, the sig not validating still doesnt mean the vin is always invalid, right? The vout script could just pop all data off and push a true. So a vin without a valid sig could still be spent...

Just the murkiness about crossing all possible vout spend scripts with all possible vins gave me pause.

James

http://www.digitalcatallaxy.com/report2015.html
100+ page annual report for SuperNET
TierNolan
Legendary
*
Offline Offline

Activity: 1232
Merit: 1083


View Profile
March 02, 2016, 11:13:11 PM
 #16

But actually, the sig not validating still doesnt mean the vin is always invalid, right? The vout script could just pop all data off and push a true. So a vin without a valid sig could still be spent...

If you are doing it as part of a protocol, you would insist that the output scripts all match the expected template.

Either use CHECKSIGVERIFY or make sure CHECKSIG is the last operation to execute.

1LxbG5cKXzTwZg9mjL3gaRE835uNQEteWF
jl777 (OP)
Legendary
*
Offline Offline

Activity: 1176
Merit: 1132


View Profile WWW
March 02, 2016, 11:15:21 PM
 #17

But actually, the sig not validating still doesnt mean the vin is always invalid, right? The vout script could just pop all data off and push a true. So a vin without a valid sig could still be spent...

If you are doing it as part of a protocol, you would insist that the output scripts all match the expected template.

Either use CHECKSIGVERIFY or make sure CHECKSIG is the last operation to execute.
certainly when I am on the side of generating the scripts, but I am working on the core side now, so have to understand the proper handling of arbitrary vins/vouts

http://www.digitalcatallaxy.com/report2015.html
100+ page annual report for SuperNET
hhanh00
Sr. Member
****
Offline Offline

Activity: 467
Merit: 266


View Profile
March 03, 2016, 12:52:22 AM
 #18

But actually, the sig not validating still doesnt mean the vin is always invalid, right? The vout script could just pop all data off and push a true. So a vin without a valid sig could still be spent...

If you are doing it as part of a protocol, you would insist that the output scripts all match the expected template.

Either use CHECKSIGVERIFY or make sure CHECKSIG is the last operation to execute.
certainly when I am on the side of generating the scripts, but I am working on the core side now, so have to understand the proper handling of arbitrary vins/vouts

Not sure if you are still wondering this, but simply put, the transaction is atomic. All the vins get transferred to the vouts if and only if every vin script pass regardless of its content. So yeah, you can create interesting combinations if you some of the scripts have different SIGHASH values.

gmaxwell
Moderator
Legendary
*
expert
Offline Offline

Activity: 4158
Merit: 8382



View Profile WWW
March 03, 2016, 07:08:41 AM
 #19

I noticed it as I found my code was assuming only a single SIGHASH type per vin, but clearly there can be multiple signers.
That is a concerning misunderstanding. I'm not sure how you'd think that-- the sighash in use is part of the ecdsa signature (input to checksig).
jl777 (OP)
Legendary
*
Offline Offline

Activity: 1176
Merit: 1132


View Profile WWW
March 03, 2016, 10:34:01 AM
 #20

I noticed it as I found my code was assuming only a single SIGHASH type per vin, but clearly there can be multiple signers.
That is a concerning misunderstanding. I'm not sure how you'd think that-- the sighash in use is part of the ecdsa signature (input to checksig).
You can sign a vin properly by multiple signers and get multiple signatures, each with a different sighash. What I assumed incorrectly was that all signers of a specific vin have to use the same sighash. Can you show me where it says that the same vin can be signed by different signers using different sighashes?

I always used bitcoind for tx signing before, but now doing it all from scratch. The context is that I was preparing the data for doing the signing and noticed I had made a wrong assumption that all sighashes would be the same, this is true in 99%+ of cases.

Anyway, please dont be alarmed, it was just an informational field that was to show what sighash mode a vin used, but it wasnt being used by anything else and it appears to need to be a vector, which is probably not worth doing as I can just iterate through all the sigs and grab the last byte.

I am making the iguana be able to be a lossless codec that uses half the space with the sigs and able to purge the sigs to get a 75% reduction in size, I estimate about 15GB size for the dataset without sigs. Do you see any reason for a non-relaying node to keep around sigs that have already been verified?

James

http://www.digitalcatallaxy.com/report2015.html
100+ page annual report for SuperNET
Pages: [1] 2 »  All
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!