-1

I'm trying to create, with BitcoinJ, something similar as the one stated in BIP16:

scriptSig: [signature] {[pubkey] OP_CHECKSIG}
scriptPubKey: OP_HASH160 [20-byte-hash of {[pubkey] OP_CHECKSIG} ] OP_EQUAL

No problems in creating the ScriptPubKey, however I'm not able to create a valid signature for the scriptSig, I get:

org.bitcoinj.core.RejectedTransactionException: Reject: tx d15fc079d0abfdcde23946dea5add84e268c71a8545d988044dbc013a84acb8d for reason 'mandatory-script-verify-flag-failed (Signature must be zero for failed CHECK(MULTI)SIG operation)' (16)

Here is my code:

    Transaction tx = new Transaction(this.params);
    Transaction orphanTx = new Transaction(this.params);
    Coin toBurn = MIN_AMOUNT;
    ECKey key = new ECKey();
    this.kit.wallet().importKey(key);
    rs = createRedeemScript(key);

    Script p2sh = ScriptBuilder.createP2SHOutputScript(rs);
    TransactionOutput to = tx.addOutput(toBurn, p2sh);
    to.setValue(to.getMinNonDustValue(this.feePerKb));

    try {
        LOGGER.info("Broadcasting transactions...");
        broadcastTransaction(tx, false);

        //[...]Waiting for tx to appear...

        //Adding change input and output from previous tx
        Transaction tTemp = new Transaction(this.params);
        SendRequest req = SendRequest.forTx(tTemp);
        req.signInputs = false;
        kit.wallet().completeTx(req);

        orphanTx.addOutput(tTemp.getOutput(tTemp.getOutput(0)));
        orphanTx.addInput(tx.getOutput(1));

        //Adding input referencing P2SH outputs from prevTx
            orphanTx.addInput(tx.getHash(), 0, tx.getOutput(0).getScriptPubKey());

        //Signing input except the one added by completeTx
            signInput(orphanTx, orphanTx.getInput(1), key, tx.getOutput(0).getScriptPubKey(), new ScriptBuilder().data(rs.getProgram()).build()), 1);

        broadcastTransaction(orphanTx, true);
        LOGGER.info("Broadcast completed.");
    } catch (Exception e) {
        throw new TransactionException(e.getMessage());
    }


private void signInput(Transaction tx, TransactionInput ti, ECKey key, Script scriptPubKey, Script scriptSig, int index){
    Sha256Hash hash = tx.hashForSignature(index, scriptPubKey, Transaction.SigHash.ALL, false);
    ECKey.ECDSASignature ecSig = key.sign(hash);
    TransactionSignature txSig = new TransactionSignature(ecSig, Transaction.SigHash.ALL, false);
    ScriptBuilder sb = new ScriptBuilder(scriptSig);
    sb.data(0, txSig.encodeToBitcoin());
    ti.setScriptSig(sb.build());
}

private Script createRedeemScript(ECKey key){
    sb.data(key.getPubKey());
    sb.addChunk(new ScriptChunk(ScriptOpCodes.OP_CHECKSIG, null));
    return sb.build();
}

private void broadcastTransaction(Transaction tx, boolean orphan) throws ExecutionException, InterruptedException, InsufficientMoneyException {
    SendRequest request = SendRequest.forTx(tx);
    request.feePerKb = this.feePerKb;
    request.shuffleOutputs = false;
    if(!orphan)
        this.kit.wallet().completeTx(request);
    else
        this.kit.wallet().signTransaction(request);
    this.kit.peerGroup().broadcastTransaction(request.tx).future().get();
}

What am I doing wrong ? Thank you very much.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Browse other questions tagged or ask your own question.