BitcoinJ manually sign P2SH output

BitcoinJ manually sign P2SH output

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.

http://bit.ly/2CGKYts

Comments

Popular posts from this blog

Need help to recover blpckchain.info wallet, my wife forgot her password and the brute force with btcrecover is not catching the password

When downloading the blockchain my application is become unusable, is there an issue with my code or am I using the BitcoinJ library incorrectly?

Mistakenly sent BTC from my personal wallet back to one of the exchange wallet addresses that I had received BTC from before - help recovering!