How to generate the digest from a raw bitcoin transaction for verifying signature of specific input?

0

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?

jaybny

Posted 2019-03-06T03:00:16.473

Reputation: 123

Answers

1

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
}

amaclin

Posted 2019-03-06T03:00:16.473

Reputation: 5 763

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 2019-03-06T15:58:00.910