I'm writing a stand alone process that needs to verify that a known UTXO is part of a new transaction with a valid signature.

Inputs [ UTXO, raw transaction, input_number ]

How do to I verify the signature for this specific input?

As I understand, depending on the SIGHASH, I would need to parse the entire transaction and replace/remove some data. However, the length bytes seem to make the entire process extremely complex.

Does a segwit transaction make everything easier? Or are there still bytes that need to be removed depending on SIGHASH?

On a side note. in general, will APIs that return "raw transactions" no longer have the signature data for segwit transactions? or are they all appended to the end?


However, the length bytes seem to make the entire process extremely complex.

Not very complex. Here is a piece of my code for generating digest for standard non-segwit transactions and sighash_all inputs (I do not need and have not tested other hashtypes).

const MyKey32 Transaction::getDigest ( const int n, const QByteArray& scr ) const
  MyByteArray data;                                 // create empty array
  MyStream stream ( s );                            // source transaction is a stream
  data.putInt32 ( stream.readU32 ( ) );             // version
  data.putVarInt ( stream.readVar ( ) );            // input count
  for ( int i ( 0 ); i < inputs; i++ )              // copy all inputs
    data.putArray ( stream.readAdvance ( 36 ), 36 );// copy 32 byte hash as is + copy 4 bytes index
    data.nop ( stream.skipVarData ( ) );            // skip original script and do nothing
    data.putPrefixedCond ( i ^ n, scr );            // script replacement: empty or given in param
    data.putInt32 ( stream.readU32 ( ) );           // sequence
  data.putVarInt ( stream.readVar ( ) );            // output count
  for ( int i ( 0 ); i < outputs; i++ )             // copy all outputs byte-by-byte
    data.putInt64 ( stream.readU64 ( ) );
    data.putPrefixed ( stream.readVarData ( ) );
  return data
      .putInt32 ( stream.readU32 ( ) )              // lock
      .putInt32 ( SIGHASH_ALL )                     // append hashcode
      .sha256d ( );                                 // double-sha256
  • Yes, I agree this base case is simple. And I too only use non-segwit sighash_all transactions coded in QT! however, my issue is trying to prove that a known UTXO was already "spent". I want to do this offline, without any access the Bitcoin network. A signed byte string that contains my UTXO in the digest is considered "spent". This is the final piece of my custom atomic swap code in a new blockchain.
    – jaybny
    Mar 6 '19 at 15:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.