3

First time on stackexchange to ask for help, sorry if i make mistakes (english is not my native language).

I try to create a valid raw transaction on C# with bouncycastle and i seems stuck, not able to find where is my mistake. I test on the testnet network and have used many sources to help myself, mainly this one. For start, i have the next address and private key

Address: mjhcWg5SvS96kk85R8G1wp7mru55UCNGY5
Public Key Hex: 0482052EF9560585ED62F046EE45C1B5F85448BCF1BD5CE36A7D35EB00C8A146C14BF99223907F9A8688E6F84B54FD747A637BB82F02E296203E735E7A6B40059F
Wif: 93U5P1qHPXAhXhiw1T15z3f1cBqFw9fWrd3Yzz1nDk8b2aRbrrM 
Private Key Hex: F7DBD21285F621F1C7A47AE7F63D06C276FE49839F4842DDEF805477936812A5

i want to use the 6.49689241 btc from the previous (testnet) transaction

912a2c3d84c8572b39c173b2bcde950cfe4ae07756bac189ace98f198d5ccb7d

and send (as test) some back to the faucet mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf

First, to build the unsigned raw transaction, i add these bytes:

01000000 (version number)
01 (number of inputs)
7dcb5c8d198fe9ac89c1ba5677e04afe0c95debcb273c1392b57c8843d2c2a91 (reversed previous tx hash)
01000000 (output index)
1976a9142de490b09ef14673af2bb4998fcb9f6b8446a84e88ac (previous tx script with its length at start) 
ffffffff (sequence)
02 (number of outputs)
496ff50200000000 (first output little endian amount. The faucet)
1976a914ac19d3fd17710e6b9a331022fe92c693fdf6659588ac (first output script with its length at start)
0046c32300000000 (second output little endian amount. My address, for change)
1976a9142de490b09ef14673af2bb4998fcb9f6b8446a84e88ac  (second script with its length at start)
00000000 (locktime)
01000000 (hash code type)

The result is

01000000017dcb5c8d198fe9ac89c1ba5677e04afe0c95debcb273c1392b57c8843d2c2a91010000001976a9142de490b09ef14673af2bb4998fcb9f6b8446a84e88acffffffff02496ff502000000001976a914ac19d3fd17710e6b9a331022fe92c693fdf6659588ac0046c323000000001976a9142de490b09ef14673af2bb4998fcb9f6b8446a84e88ac0000000001000000

I then retrieve the transaction hash by pushing the raw transaction in a double SHA256 function that return me

f64b6480a2888596636d4995153e990ce95582a1308c9c568d2698e6dc1f7893

Then, i sign with the private key hex (prvkeyHex) the transaction hash (txHash) with this function:

X9ECParameters curve = SecNamedCurves.GetByName("secp256k1");
ECDomainParameters dom = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H)
ECKeyParameters params = new ECPrivateKeyParameters(new BigInteger(1, prvkeyHex), dom);
ECDsaSigner signer = new ECDsaSigner();
signer.Init(true, params);
BigInteger[] sig = signer.GenerateSignature(txHash);
MemoryStream ms = new MemoryStream(72);
DerSequenceGenerator seq = new DerSequenceGenerator(ms);
seq.AddObject(new DerInteger(sig[0]));
seq.AddObject(new DerInteger(sig[1]));
seq.Close();
byte[] signature = ms.ToArray();

Which return me a byte array of max 72 bytes length starting by 30. In my last test:

3045022100abceff62d3192b686c405d10516ff0e6f9ff221c00284d766200a6abb42361be02202972970369d6b9308467e15ebafd3f6b9faf111886071e3c429b34e9407e8d23

I then construct my final scriptSig with the public key hex and their lengths who result as

483045022100abceff62d3192b686c405d10516ff0e6f9ff221c00284d766200a6abb42361be02202972970369d6b9308467e15ebafd3f6b9faf111886071e3c429b34e9407e8d2301410482052ef9560585ed62f046ee45c1b5f85448bcf1bd5ce36a7d35eb00c8a146c14bf99223907f9a8688e6f84b54fd747a637bb82f02e296203e735e7a6b40059f

I finally built my signed raw transaction:

01000000 (version number)
01 (number of inputs)
7dcb5c8d198fe9ac89c1ba5677e04afe0c95debcb273c1392b57c8843d2c2a91 (reversed previous tx hash)
01000000 (output index)
8b (scriptSig length)
483045022100abceff62d3192b686c405d10516ff0e6f9ff221c00284d766200a6abb42361be02202972970369d6b9308467e15ebafd3f6b9faf111886071e3c429b34e9407e8d2301410482052ef9560585ed62f046ee45c1b5f85448bcf1bd5ce36a7d35eb00c8a146c14bf99223907f9a8688e6f84b54fd747a637bb82f02e296203e735e7a6b40059f (scriptSig)
ffffffff (sequence)
02 (number of outputs)
496ff50200000000 (first output little endian amount. The faucet)
1976a914ac19d3fd17710e6b9a331022fe92c693fdf6659588ac (first output script with its length at start)
0046c32300000000 (second output little endian amount. My address, for change)
1976a9142de490b09ef14673af2bb4998fcb9f6b8446a84e88ac  (second script with its length at start)
00000000 (locktime)

The final result give me that signed raw transaction

01000000017dcb5c8d198fe9ac89c1ba5677e04afe0c95debcb273c1392b57c8843d2c2a91010000008b483045022100abceff62d3192b686c405d10516ff0e6f9ff221c00284d766200a6abb42361be02202972970369d6b9308467e15ebafd3f6b9faf111886071e3c429b34e9407e8d2301410482052ef9560585ed62f046ee45c1b5f85448bcf1bd5ce36a7d35eb00c8a146c14bf99223907f9a8688e6f84b54fd747a637bb82f02e296203e735e7a6b40059fffffffff02496ff502000000001976a914ac19d3fd17710e6b9a331022fe92c693fdf6659588ac0046c323000000001976a9142de490b09ef14673af2bb4998fcb9f6b8446a84e88ac00000000

But now, when i try to send that signed raw transaction on the testnet network by a web service, everytime i get an error. sandbox.smartbit.com.au/txs/pushtx return me

"PUSH TRANSACTION ERROR: 16: MANDATORY-SCRIPT-VERIFY-FLAG-FAILED (SCRIPT EVALUATED WITHOUT ERROR BUT FINISHED WITH A FALSE/EMPTY TOP STACK ELEMENT)"

live.blockcypher.com/btc-testnet/pushtx/ return me

"Error sending transaction: Error running script for input 0 referencing 912a2c3d84c8572b39c173b2bcde950cfe4ae07756bac189ace98f198d5ccb7d at 1: Script was NOT verified successfully.."

same with tbtc.blockr.io/tx/push

I'm far from mastering bitcoin or c#, i am learning (and want to learn how that work). Is anyone see where is my mistake ? Thanks

2 Answers 2

1

The signature you produced is correct but for a wrong "message", which is the only mistake that I could find. This is what you sign:

f64b6480a2888596636d4995153e990ce95582a1308c9c568d2698e6dc1f7893

Which is wrong (since you reversed the has result). Instead you should have signed the actual result you get from your SHA256(SHA256(<bytes>)) to your signing function, meaning this instead:

93781fdce698268d569c8c30a18255e90c993e1595496d63968588a280644bf6

There are a couple of places where we reverse the hash result and this is not one of them. Here you are simply hashing the serialized transaction to turn the size of it from an arbitrary length to a fixed 32 byte size so that you can sign it using ECDSA scheme.

There is an additional possible problem with directly using BouncyCastle or any similar library that are designed for cryptography in general not for bitcoin, where the signature they return may have an s value (the second BigInteger in your signature) that is bigger than curve N/2. In which case you will have to change it to s' by calculating s' = N - s.

0

Why don't you use NBitcoin library to create a raw transaction and post it to blockr.io or whatever API provider you're using? NBitcoin is a great library for C# cryptocurrency developers.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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