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

sendrawtransaction and txn-mempool-conflict

couldn't connect to server: EOF reached (code 1)