Author

Topic: What exactly is "signed" for each UTXO in a Bitcoin tx? (Read 1029 times)

legendary
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
My badge of honor: https://blockchain.info/tx/9615d019abcb8ad4aa1361deeb6972c3afbecf97841ab07afbc6eaac5608813b

And now I do now feel a bit more "legendary". Grin
legendary
Activity: 1260
Merit: 1019
My suggestion is (not for you, but for everyone):

Do not waste blockchain space with your test transactions!
Use testnet instead!
(And send main-net coins directly to my adderss)
legendary
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
Damn - stupid coding mistakes. Sad

Those "sizeof( hash )" should have been c_num_hash_bytes instead. Doh!

Anyway here is my first self-created "signed Bitcoin tx" is as follows:

01000000013c9eab4935d1b8fe2bad3af1c443c2c61ab8212c3f45c2ba59ff4a2e93c481e200000 0006b483045022100d06e7cf940032fdbba04a35b07bfec4359c79936e00c2b31c78b0ec6d1fe79 960220269065708cec6c3436dc4a65b7841e09eaf9d1eec98a52930ee747290cb7b22b012103bd6 f03d746e0127a45c6f8ba39326da9d7a00efce7a74828e2e5bef85e37f8feffffffff01204e0000 000000001976a91406c1991c6466a550b66931ea48970cfd17ff51b388ac00000000

Code:
01000000013c9eab4935d1b8fe2bad3af1c443c2c61ab8212c3f45c2ba59ff4a2e93c481e2000000006b483045022100d06e7cf940032fdbba04a35b07bfec4359c79936e00c2b31c78b0ec6d1fe79960220269065708cec6c3436dc4a65b7841e09eaf9d1eec98a52930ee747290cb7b22b012103bd6f03d746e0127a45c6f8ba39326da9d7a00efce7a74828e2e5bef85e37f8feffffffff01204e0000000000001976a91406c1991c6466a550b66931ea48970cfd17ff51b388ac00000000

Quite a feeling of achievement (it did take me a whole day). Grin

Thanks a lot for the help @amaclin (if nothing else you helped me to "keep trying until I conquered it").
legendary
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
My code for generating the sig is as follows:

Code:
  const int c_num_hash_bytes = 32;

   void sign_message( const unsigned char hash[ c_num_hash_bytes ], vector< unsigned char >& signature )
   {
      ECDSA_SIG* p_sig = ECDSA_do_sign( &hash[ 0 ], sizeof( hash ), p_key );
      if( !p_sig )
         throw runtime_error( "unexpected failure for ECDSA_do_sign in sign_message" );

      signature.clear( );

      unsigned int size = ECDSA_size( p_key );
      signature.resize( size );

      unsigned char* p = &signature[ 0 ];
      size = i2d_ECDSA_SIG( p_sig, &p );
      signature.resize( size );

      ECDSA_SIG_free( p_sig );
   }

I have then checked whether the sig should be valid with this function:
Code:
  bool verify_signature( const unsigned char hash[ c_num_hash_bytes ], vector< unsigned char >& signature )
   {
      bool okay = false;

      if( ECDSA_verify( 0, &hash[ 0 ], sizeof( hash ), &signature[ 0 ], signature.size( ), p_key ) == 1 )
         okay = true;

      return okay;
   }


It tells me it should be okay (so again I can only think I have got something wrong with "what I signed").
legendary
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
So I worked out I had screwed up with the signature generation.

The latest version I've tried is now this:

Code:
01000000013c9eab4935d1b8fe2bad3af1c443c2c61ab8212c3f45c2ba59ff4a2e93c481e2000000006b483045022100dba294c0766ff7d2eb9e308c13ec22da1ec8398ecb20111ead35c3776796983402207feaef74dbefeffe840a570ce7045d5e5e3f2c7dbd63ef16e7da841f2c8eda24012103bd6f03d746e0127a45c6f8ba39326da9d7a00efce7a74828e2e5bef85e37f8feffffffff01204e0000000000001976a91406c1991c6466a550b66931ea48970cfd17ff51b388ac00000000

But it still doesn't like the sig. Sad
legendary
Activity: 1260
Merit: 1019
ok, data looks correct

Code:
version  01000000
inputs   01
hash     3c9e ab49 35d1 b8fe-2bad 3af1 c443 c2c6-1ab8 212c 3f45 c2ba-59ff 4a2e 93c4 81e2
index    00000000
len      19
script   76a914 3a89c372f5308cb58828979bb624f7e8822672ed88ac
seq      ffff ffff
outs     01
value    204e000000000000
output   1976a91406c1991c6466a550b66931ea48970cfd17ff51b388ac
lock     00000000
type     01000000

And I got the same hash as yours but in different byte order "c279b67fa34c6aa2062bb2668dd45b43f8112208b5454f89b90538be907e853f"
(ok, my bytes are reversed (as all in bitcoin), yours are fine)


legendary
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
sorry, i am wrong
wait please

No worries at all - am very glad for your help. Smiley
legendary
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
Okay so I now have this being signed:

01000000013c9eab4935d1b8fe2bad3af1c443c2c61ab8212c3f45c2ba59ff4a2e93c481e200000 00000ffffffff01204e0000000000001976a91406c1991c6466a5
50b66931ea48970cfd17ff51b388ac0000000001000000

Code:
01000000013c9eab4935d1b8fe2bad3af1c443c2c61ab8212c3f45c2ba59ff4a2e93c481e20000000000ffffffff01204e0000000000001976a91406c1991c6466a550b66931ea48970cfd17ff51b388ac0000000001000000

with the final hash as: 6ad11c524c8ffa782800d4ff8c98a174ceff1f1004a497a8f8f836a7ed15aacf

It is still failing with an invalid sig. Sad
legendary
Activity: 1260
Merit: 1019
sorry, i am wrong
wait please
legendary
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
I do see three lines and I do not understand where are they from.
Please post the data, which you pass to sha256d method

...

Post them here.

These were the bytes I signed (repeated in a "code" if that might make it easier for copy and paste):

01000000013c9eab4935d1b8fe2bad3af1c443c2c61ab8212c3f45c2ba59ff4a2e93c481e200000 0001976a9143a89c372f5308cb58828
979bb624f7e8822672ed88acffffffff01204e0000000000001976a91406c1991c6466a550b6693 1ea48970cfd17ff51b388ac0000000001000000

Code:
01000000013c9eab4935d1b8fe2bad3af1c443c2c61ab8212c3f45c2ba59ff4a2e93c481e2000000001976a9143a89c372f5308cb58828979bb624f7e8822672ed88acffffffff01204e0000000000001976a91406c1991c6466a550b66931ea48970cfd17ff51b388ac0000000001000000

The final hash I got for this is: 3f857e90be3805b9894f45b5082211f8435bd48d66b22b06a26a4ca37fb679c2
legendary
Activity: 1260
Merit: 1019
I guess that the bytes that I signed were somehow incorrect
Post them here.

legendary
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
Hmm... so it would appear that my sig is invalid so somehow I guess that the bytes that I signed were somehow incorrect - anyone see what I missed?
legendary
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer

Thanks for that (it was helpful) and I think I am "very close" with this attempt:

01000000013c9eab4935d1b8fe2bad3af1c443c2c61ab8212c3f45c2ba59ff4a2e93c481e200000 0006c4930460221008acf9a9426220a6447d4e7062e796813b39208d242e4ae467d69b5804a25db 150221008b3d68c9b64517c4c011d3074c4cc04196f51f686178d59f11ae022a84b3574e012103b d6f03d746e0127a45c6f8ba39326da9d7a00efce7a74828e2e5bef85e37f8feffffffff01204e00 00000000001976a91406c1991c6466a550b66931ea48970cfd17ff51b388ac00000000

Code:
01000000013c9eab4935d1b8fe2bad3af1c443c2c61ab8212c3f45c2ba59ff4a2e93c481e2000000006c4930460221008acf9a9426220a6447d4e7062e796813b39208d242e4ae467d69b5804a25db150221008b3d68c9b64517c4c011d3074c4cc04196f51f686178d59f11ae022a84b3574e012103bd6f03d746e0127a45c6f8ba39326da9d7a00efce7a74828e2e5bef85e37f8feffffffff01204e0000000000001976a91406c1991c6466a550b66931ea48970cfd17ff51b388ac00000000

But alas it is rejected (-22). Sad

It appears to decode fine so am wondering whether it is the sig that I've got wrong or if it is something else?
Code:
{
   "lock_time":0,
   "inputs":[
      {
         "prev_out":{
            "index":0,
            "hash":"e281c4932e4aff59bac2453f2c21b81ac6c243c4f13aad2bfeb8d13549ab9e3c"
         },
         "script":"4930460221008acf9a9426220a6447d4e7062e796813b39208d242e4ae467d69b5804a25db150221008b3d68c9b64517c4c011d3074c4cc04196f51f686178d59f11ae022a84b3574e012103bd6f03d746e0127a45c6f8ba39326da9d7a00efce7a74828e2e5bef85e37f8fe"
      }
   ],
   "vout_sz":1,
   "hash":"62d03bf1444455ce2ff343a8f0e56b705b9ed4558768854f6e700e8a7451b787",
   "vin_sz":1,
   "out":[
      {
         "address":"1ciyam3htJit1feGa26p2wQ4aw6KFTejU",
         "script_string":"OP_DUP OP_HASH160 06c1991c6466a550b66931ea48970cfd17ff51b3 OP_EQUALVERIFY OP_CHECKSIG",
         "value":20000,
         "script":"76a91406c1991c6466a550b66931ea48970cfd17ff51b388ac"
      }
   ],
   "size":193,
   "version":1
}

The sig is applied to two SHA256s of the following:

01000000013c9eab4935d1b8fe2bad3af1c443c2c61ab8212c3f45c2ba59ff4a2e93c481e200000 0001976a9143a89c372f5308cb58828979bb624f7e8822672ed88acffffffff01204e0000000000 001976a91406c1991c6466a550b66931ea48970cfd17ff51b388ac0000000001000000

Code:
01000000013c9eab4935d1b8fe2bad3af1c443c2c61ab8212c3f45c2ba59ff4a2e93c481e2000000001976a9143a89c372f5308cb58828979bb624f7e8822672ed88acffffffff01204e0000000000001976a91406c1991c6466a550b66931ea48970cfd17ff51b388ac0000000001000000

With the final hash being: 3f857e90be3805b9894f45b5082211f8435bd48d66b22b06a26a4ca37fb679c2
legendary
Activity: 1260
Merit: 1019
legendary
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
I am sure this has been asked before but my poor search skills have still not found the answer so I am hoping someone could save me a bit of time.

I have now written code to create raw transactions (of the "standard" variety) and one such example is the following:

Code:
0100000002bad39efeeb23cc53077749d728a048092a767d552109ba35a3ded464a81636960000000000ffffffff8a048092a767d552109ba35a3ded464a8163696bad39efeeb23cc53077749d726400000000ffffffff02e8030000000000001976a914f54a5851e9372b87810a8e60cdd2e7cfd80b6e3188ac400d0300000000001976a914f54a5851e9372b87810a8e60cdd2e7cfd80b6e3188ac00000000

I want to now be able to "sign" the raw transactions (without using Bitcoin to do so - just doing it with my own code). I have all the source code needed to do this (in terms of the crypto stuff) but what I can't work out is "what is the actual message that is signed"?

(i.e. exactly what binary input do I pass to the ECDSA_do_sign function for each UTXO?)
Jump to: