Skip to content

Conversation

@theStack
Copy link
Contributor

@theStack theStack commented Jul 3, 2023

There are several instances in functional tests and the framework (MiniWallet, feature_block.py, p2p_segwit.py) where we create a legacy ECDSA signature for a certain transaction's input by doing the following steps:

  1. calculate the LegacySignatureHash with the desired sighash type
  2. create the actual digital signature by calling ECKey.sign_ecdsa on the signature message hash calculated above
  3. put the DER-encoded result as CScript data push into tx input's scriptSig

Create a new helper sign_input_legacy which hides those details and takes only the necessary parameters (tx, input index, relevant scriptPubKey, private key, sighash type [SIGHASH_ALL by default]). For further convenience, the signature is prepended to already existing data-pushes in scriptSig, in order to avoid rehashing the transaction after calling the new signing function.

There are several instances in functional tests and the framework
(MiniWallet, feature_block.py, p2p_segwit.py) where we create a legacy
ECDSA signature for a certain transaction's input by doing the following
steps:
    1) calculate the `LegacySignatureHash` with the desired sighash type
    2) create the actual digital signature by calling `ECKey.sign_ecdsa`
       on the signature message hash calculated above
    3) put the DER-encoded result as CScript data push into
       tx input's scriptSig

Create a new helper `sign_input_legacy` which hides those details and
takes only the necessary parameters (tx, input index, relevant
scriptPubKey, private key, sighash type [SIGHASH_ALL by default]). For
further convenience, the signature is prepended to already existing
data-pushes in scriptSig, in order to avoid rehashing the transaction
after calling the new signing function.
@DrahtBot
Copy link
Contributor

DrahtBot commented Jul 3, 2023

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Reviews

See the guideline for information on the review process.

Type Reviewers
ACK dimitaracev, pinheadmz, achow101

If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

@DrahtBot DrahtBot added the Tests label Jul 3, 2023
@fanquake fanquake requested a review from pinheadmz July 4, 2023 11:13
@dimitaracev
Copy link
Contributor

ACK 5cf4427

Copy link
Member

@pinheadmz pinheadmz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 5cf4427

Reviewed all code. Built and ran tests locally. Nice clean up!

Also - do you think we need a segwitV0 function like this as well? As far as I can grep there's only 2 such signing operations in p2p_segwit.py so maybe that's more work than its worth.

Show Signature
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

ACK 5cf44275c8ca8c32d238f37f717d78e9823f44c2
-----BEGIN PGP SIGNATURE-----

iQIzBAEBCAAdFiEE5hdzzW4BBA4vG9eM5+KYS2KJyToFAmSlyacACgkQ5+KYS2KJ
yToilhAA0xbzuJ7W+WAuxPjb/FbZU+aOlRHm5NJrxEWJXv4AUcyykkioGt/EfOKQ
w8iBlgQzr4HHdnJeDryZ+d+4vJOdPjrF2h9HH+OLnY/WihGEpPV2dtjFqeiZchtJ
dI7mryFHtNa8mpMAW7zJZ00jGZuYd9BTcKdE2JK/izjam1JwN1l6BkLnB/6QSfXS
Twg5HZbkHboa9ojYiz6KHt3lodMH+xWdC2TVQKO5rthjZ2tVws/4AWxpsnnHk6wL
VhMgo1vKKZOF3d0f29fbXb1mPaiCfz+BBPCSZZrj+Uzvpz9eLa71vGo7npudfO9H
tvxQnL42tRdUvftmlMZh6uneBuAICrjeELvRdu0+9CO4PRlbno2BMhNS1BB1+rwO
XJgq4Tqzv5eUBywxWF97zfIXDPn/8YjSVB0YAAOBAArSmDRo78aMXdPTF7+nT07T
xCS06fDj4wi2XDD00nuB6uPVfYSHYfZJ7vSaZQlZFYVSfScblFD2xgM4kcYkmz4c
VlqpTxI3nmx6enjNvw4t8T3OeXEkO/n7shiKXJ1v6VMNbefyTZtW2833wZTbWU4O
8oZkZoWSdd1S4yzU3Q1FQm0JWscSPYiweexHf2xIP2apWxhoCW0gSOdwTfCtbJcG
ClHU26Qms4nqlLK6YvTXlaEAB1x8QCLqRr95lpbkOAv/9Iv7xlY=
=WdbY
-----END PGP SIGNATURE-----

pinheadmz's public key is on keybase

else:
return (hash256(msg), err)

def sign_input_legacy(tx, input_index, input_scriptpubkey, privkey, sighash_type=SIGHASH_ALL):
Copy link
Member

@pinheadmz pinheadmz Jul 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth checking things like the input index exists and sighash is only one byte? Can we safely assume that tx.vin[input_index].scriptSig will always be a bytes object? (Even if it is empty?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the input index is checked in LegacySignatureMsg (which is in turn called by LegacySignatureHash):

if inIdx >= len(txTo.vin):
return (None, "inIdx %d out of range (%d)" % (inIdx, len(txTo.vin)))

For sighash_type it might be nice to add a type annotation, though I don't know if the byte range (0..255) can be specified exactly (currently that value is not set explicitly, as all our call-sites use the default SIGHASH_ALL). As for tx.vin[input_index].scriptSig: it's default-initialized with an empty byte-string b'' (see CTxIn.__init__), and if the user sets it to a CScript instance that's also okay, as this is derived from bytes, so I think we can safely assume that the type is okay.

@theStack
Copy link
Contributor Author

theStack commented Jul 6, 2023

Also - do you think we need a segwitV0 function like this as well? As far as I can grep there's only 2 such signing operations in p2p_segwit.py so maybe that's more work than its worth.

Good point -- I think it would be nice to introduce similar functions for other signature types (e.g. sign_input_segwitv0) for consistency reasons. Might be worth a follow-up, together with some other improvements pointed out in #28025 (comment) (type annotations, input range checks etc.)? If anyone wants to tackle that, feel free to ping me as reviewer.

@achow101
Copy link
Member

ACK 5cf4427

@achow101 achow101 merged commit 357e3f6 into bitcoin:master Jul 11, 2023
@theStack theStack deleted the 202307-test-deduplicate_legacy_input_signing branch July 11, 2023 21:28
theStack added a commit to theStack/bitcoin that referenced this pull request Jul 25, 2023
achow101 added a commit that referenced this pull request Sep 20, 2023
…tx inputs

83d7cfd test: refactor: deduplicate segwitv0 ECDSA signing for tx inputs (Sebastian Falbesoner)

Pull request description:

  This PR is a simple follow-up for #28025. It introduces a `signing_input_segwitv0` helper in order to deduplicate the following steps needed to create a segwitv0 ECDSA signature:
  1. calculate the `SegwitV0SignatureHash` with the desired sighash type
  2. create the actual digital signature by calling ECKey.sign_ecdsa on the signature message hash calculated above
  3. put the DER-encoded result (plus sighash byte) at the bottom of the witness stack

ACKs for top commit:
  achow101:
    ACK 83d7cfd
  pinheadmz:
    code review ACK at 83d7cfd

Tree-SHA512: b8e55409ddc9ddb14cfc06daeb4730d7750a4632f175f88dcac6ec4d216e71fd4a7eee325a64d6ebba3b33be50bcd30c2de7400f834c01abb67e52840d9823b6
Frank-GER pushed a commit to syscoin/syscoin that referenced this pull request Sep 27, 2023
@bitcoin bitcoin locked and limited conversation to collaborators Jul 10, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants