use of org.bitcoinj.script.ScriptChunk 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.");
}
}
use of org.bitcoinj.script.ScriptChunk in project balzac by balzac-lang.
the class AbstractScriptBuilder method optimize.
/*
* Optimization step
*/
private static ImmutableList<ScriptChunk> optimize(ImmutableList<ScriptChunk> scriptChunks) {
if (scriptChunks.size() == 0 || scriptChunks.size() == 1) {
return scriptChunks;
}
ScriptChunk ch1 = scriptChunks.get(0);
ScriptChunk ch2 = scriptChunks.get(1);
if (ch1.equalsOpCode(ScriptOpCodes.OP_TOALTSTACK) && ch2.equalsOpCode(ScriptOpCodes.OP_FROMALTSTACK)) {
return optimize(scriptChunks.subList(2, scriptChunks.size()));
}
return ImmutableList.<ScriptChunk>builder().add(scriptChunks.get(0)).addAll(optimize(scriptChunks.subList(1, scriptChunks.size()))).build();
}
use of org.bitcoinj.script.ScriptChunk in project balzac by balzac-lang.
the class AbstractScriptBuilderWithVar method setAllSignatures.
/**
* Replace all the signatures placeholder with the actual signatures.
* Each placeholder is already associated with the key and the modifiers.
* @param tx the transaction to be signed
* @param inputIndex the index of the input that will contain this script
* @param outScript the redeemed output script
* @return a <b>copy</b> of this builder
* @throws KeyStoreException if an error occurs retrieving private keys
*/
@SuppressWarnings("unchecked")
public T setAllSignatures(ECKeyStore keystore, Transaction tx, int inputIndex, byte[] outScript) throws KeyStoreException {
List<ScriptChunk> newChunks = new ArrayList<>();
for (ScriptChunk chunk : getChunks()) {
ScriptBuilder2 sb = new ScriptBuilder2();
if (isSignature(chunk)) {
String mapKey = getMapKey(chunk);
SignatureUtil sig = this.signatures.get(mapKey);
checkState(keystore != null, "keystore must be set to retrieve the private keys");
checkState(keystore.containsKey(sig.keyID), "key " + sig.keyID + " not found on the specified keystore");
ECKey key = keystore.getKey(sig.keyID);
SigHash hashType = sig.hashType;
boolean anyoneCanPay = sig.anyoneCanPay;
// check the key is correct when P2PKH
// Script s = new Script(outScript);
// if (s.isSentToAddress()) {
// checkState(Arrays.equals(s.getPubKeyHash(), key.getPubKeyHash()));
// }
TransactionSignature txSig = tx.calculateSignature(inputIndex, key, outScript, hashType, anyoneCanPay);
Sha256Hash hash = tx.hashForSignature(inputIndex, outScript, (byte) txSig.sighashFlags);
boolean isValid = ECKey.verify(hash.getBytes(), txSig, key.getPubKey());
checkState(isValid);
checkState(txSig.isCanonical());
sb.data(txSig.encodeToBitcoin());
} else {
sb.addChunk(chunk);
}
newChunks.addAll(sb.getChunks());
}
super.getChunks().clear();
super.getChunks().addAll(newChunks);
this.signatures.clear();
return (T) this;
}
Aggregations