use of org.bitcoinj.wallet.RedeemData in project bisq-core by bisq-network.
the class WalletService method signTransactionInput.
// /////////////////////////////////////////////////////////////////////////////////////////
// Sign tx
// /////////////////////////////////////////////////////////////////////////////////////////
public static void signTransactionInput(Wallet wallet, KeyParameter aesKey, Transaction tx, TransactionInput txIn, int index) {
KeyBag maybeDecryptingKeyBag = new DecryptingKeyBag(wallet, aesKey);
if (txIn.getConnectedOutput() != null) {
try {
// We assume if its already signed, its hopefully got a SIGHASH type that will not invalidate when
// we sign missing pieces (to check this would require either assuming any signatures are signing
// standard output types or a way to get processed signatures out of script execution)
txIn.getScriptSig().correctlySpends(tx, index, txIn.getConnectedOutput().getScriptPubKey(), Script.ALL_VERIFY_FLAGS);
log.warn("Input {} already correctly spends output, assuming SIGHASH type used will be safe and skipping signing.", index);
return;
} catch (ScriptException e) {
// Expected.
}
Script scriptPubKey = txIn.getConnectedOutput().getScriptPubKey();
RedeemData redeemData = txIn.getConnectedRedeemData(maybeDecryptingKeyBag);
checkNotNull(redeemData, "Transaction exists in wallet that we cannot redeem: %s", txIn.getOutpoint().getHash());
txIn.setScriptSig(scriptPubKey.createEmptyInputScript(redeemData.keys.get(0), redeemData.redeemScript));
TransactionSigner.ProposedTransaction propTx = new TransactionSigner.ProposedTransaction(tx);
Transaction partialTx = propTx.partialTx;
txIn = partialTx.getInput(index);
if (txIn.getConnectedOutput() != null) {
// If we dont have a sig we don't do the check to avoid error reports of failed sig checks
final List<ScriptChunk> chunks = txIn.getConnectedOutput().getScriptPubKey().getChunks();
if (!chunks.isEmpty() && chunks.get(0).data != null && chunks.get(0).data.length > 0) {
try {
// We assume if its already signed, its hopefully got a SIGHASH type that will not invalidate when
// we sign missing pieces (to check this would require either assuming any signatures are signing
// standard output types or a way to get processed signatures out of script execution)
txIn.getScriptSig().correctlySpends(tx, index, txIn.getConnectedOutput().getScriptPubKey(), Script.ALL_VERIFY_FLAGS);
log.warn("Input {} already correctly spends output, assuming SIGHASH type used will be safe and skipping signing.", index);
return;
} catch (ScriptException e) {
// Expected.
}
}
redeemData = txIn.getConnectedRedeemData(maybeDecryptingKeyBag);
scriptPubKey = txIn.getConnectedOutput().getScriptPubKey();
checkNotNull(redeemData, "redeemData must not be null");
ECKey pubKey = redeemData.keys.get(0);
if (pubKey instanceof DeterministicKey)
propTx.keyPaths.put(scriptPubKey, (((DeterministicKey) pubKey).getPath()));
ECKey key;
if ((key = redeemData.getFullKey()) == null) {
log.warn("No local key found for input {}", index);
return;
}
Script inputScript = txIn.getScriptSig();
byte[] script = redeemData.redeemScript.getProgram();
try {
TransactionSignature signature = partialTx.calculateSignature(index, key, script, Transaction.SigHash.ALL, false);
inputScript = scriptPubKey.getScriptSigWithSignature(inputScript, signature.encodeToBitcoin(), 0);
txIn.setScriptSig(inputScript);
} catch (ECKey.KeyIsEncryptedException e1) {
throw e1;
} catch (ECKey.MissingPrivateKeyException e1) {
log.warn("No private key in keypair for input {}", index);
}
} else {
log.warn("Missing connected output, assuming input {} is already signed.", index);
}
} else {
log.error("Missing connected output, assuming already signed.");
}
}
Aggregations