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
Post a Comment