This is sort of a cross-post of my question on
StackExchange, but with a different example.
I have the following unsigned raw transaction taken from
this example:
01000000
01
eccf7e3034189b851985d871f91384b8ee357cd47c3024736e5676eb2debb3f2
01000000
19
76a914010966776006953d5567439e5e39f86a0d273bee88ac
ffffffff
01
605af40500000000
19
76a914097072524438d003d23a2f23edb65aae1bb3e46988ac
00000000
01000000
I can parse it into human readable form with the JSON-RPC api:
curl --user USERNAME --data-binary '{"id":"t0", "method": "decoderawtransaction", "params": [
"0100000001eccf7e3034189b851985d871f91384b8ee357cd47c3024736e5676eb2debb3f2010000001976a914010966776006953d5567439e5e39f86a0d273bee88acffffffff01605af405000000001976a914097072524438d003d23a2f23edb65aae1bb3e46988ac0000000001000000"]
{"result":{"txid":"7584a4e1f3b46ea7af8230b761711dd4f03494f26d5da86995aa80c5b54e6a59","version":1,"locktime":0,"vin":[{"txid":"f2b3eb2deb76566e7324307cd47c35eeb88413f971d88519859b1834307ecfec","vout":1,"scriptSig":{"asm":"OP_DUP OP_HASH160 010966776006953d5567439e5e39f86a0d273bee OP_EQUALVERIFY OP_CHECKSIG","hex":"76a914010966776006953d5567439e5e39f86a0d273bee88ac"},"sequence":4294967295}],"vout":[{"value":0.99900000,"n":0,"scriptPubKey":{"asm":"OP_DUP OP_HASH160 097072524438d003d23a2f23edb65aae1bb3e469 OP_EQUALVERIFY OP_CHECKSIG","hex":"76a914097072524438d003d23a2f23edb65aae1bb3e46988ac","reqSigs":1,"type":"pubkeyhash","addresses":["1runeksijzfVxyrpiyCY2LCBvYsSiFsCm"]}}]},"error":null,"id":"t0"}
But I can't sign it, not even when I add the corresponding previous transaction and private key (it's not a real transaction though).
curl --user USERNAME --data-binary '{"id":"t0", "method": "signrawtransaction", "params": [
"0100000001eccf7e3034189b851985d871f91384b8ee357cd47c3024736e5676eb2debb3f2010000001976a914010966776006953d5567439e5e39f86a0d273bee88acffffffff01605af405000000001976a914097072524438d003d23a2f23edb65aae1bb3e46988ac0000000001000000",
["f2b3eb2deb76566e7324307cd47c35eeb88413f971d88519859b1834307ecfec"],
["2g82vgrZTviKG5sN1g2VM7FHgHTm16ej4gmr8ECMzab6"]
]}' http://127.0.0.1:8332/
{"result":null,"error":{"code":-22,"message":"TX decode failed"},"id":"t0"}
I also think it's strange that I get a TX decode error here and I acutally suspect is not the correct message, see my
Github ticket.
This makes it hard for me to figure out what I'm doing wrong in my attempt to sign a transaction in ruby.
@keypair = OpenSSL::PKey::EC.new("secp256k1")
@keypair.private_key = @YourPrivateKey.hex
@keypair.public_key = ::OpenSSL::PKey::EC::Point.from_hex(@keypair.group, @YourPublicKey)
transaction_hash_bytes = [sha_second].pack("H*")
signature_bytes = @keypair.dsa_sign_asn1(transaction_hash_bytes)
signature = signature_bytes.unpack("H*").first
The pack("H*") and unpack are just guesses, but most similar to what I did with SHA. The result is a hex of varying length (70-72 bytes).
Each time you make a signature with
secp256k1 it's different, so I can't use the signature that's provided in the example as a reference point. The only way I know how to test it is to sign a real transaction and try to send it through
Blockchain.info's push transaction page.
So I tried this with a real transaction of my own, but then I get a "signature invalid" message. I'm assuming that message means what it says.
If I try to
sendrawtransaction through JSON-RPC I just get
{"result":null,"error":{"code":-22,"message":"TX rejected"},"id":"t0"}. I'm able to perform
decoderawtransaction on both my unsigned and signed real transaction. But when I try to sign it using the JSON-RPC I get the same error as I showed above.
The signature is applied to the sha-256^2 hash of the unsigned transaction. I'm able to reproduce this hash in ruby using the example's input parameters, therefore I assume my script is correct up to that point.
I suspect that I'm doing something wrong related to encoding when I sign the hash. The sha-256 methods in ruby expect a Bignum ("10".hex => 16 ) as input and produce a string as output with human readable hex values, which I can then convert to a Bignum again. However it's less clear what the methods for signing using secp256k1 expect for input and provide as output. It just takes a string and returns a string, regardless of what's in it. It contains a method that allows you to check a signature, which works when I feed the output back into it, but that doesn't say much.
As far as I know nobody has (publicly) signed a bitcoin transaction using Ruby before, so I can't rule out the possibility of a bug.
Is there a way to verify a signature without trying to actually send the transaction?