Search in sources :

Example 6 with ScriptChunk

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.");
    }
}
Also used : Script(org.bitcoinj.script.Script) TransactionSigner(org.bitcoinj.signers.TransactionSigner) ECKey(org.bitcoinj.core.ECKey) TransactionSignature(org.bitcoinj.crypto.TransactionSignature) KeyBag(org.bitcoinj.wallet.KeyBag) DecryptingKeyBag(org.bitcoinj.wallet.DecryptingKeyBag) RedeemData(org.bitcoinj.wallet.RedeemData) ScriptChunk(org.bitcoinj.script.ScriptChunk) DecryptingKeyBag(org.bitcoinj.wallet.DecryptingKeyBag) ScriptException(org.bitcoinj.core.ScriptException) Transaction(org.bitcoinj.core.Transaction) DeterministicKey(org.bitcoinj.crypto.DeterministicKey)

Example 7 with ScriptChunk

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();
}
Also used : ScriptChunk(org.bitcoinj.script.ScriptChunk)

Example 8 with ScriptChunk

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;
}
Also used : SigHash(org.bitcoinj.core.Transaction.SigHash) Sha256Hash(org.bitcoinj.core.Sha256Hash) ArrayList(java.util.ArrayList) ECKey(org.bitcoinj.core.ECKey) TransactionSignature(org.bitcoinj.crypto.TransactionSignature) ScriptChunk(org.bitcoinj.script.ScriptChunk)

Aggregations

ScriptChunk (org.bitcoinj.script.ScriptChunk)8 ECKey (org.bitcoinj.core.ECKey)2 TransactionSignature (org.bitcoinj.crypto.TransactionSignature)2 Script (org.bitcoinj.script.Script)2 ArrayList (java.util.ArrayList)1 ScriptException (org.bitcoinj.core.ScriptException)1 Sha256Hash (org.bitcoinj.core.Sha256Hash)1 Transaction (org.bitcoinj.core.Transaction)1 SigHash (org.bitcoinj.core.Transaction.SigHash)1 DeterministicKey (org.bitcoinj.crypto.DeterministicKey)1 ScriptBuilder (org.bitcoinj.script.ScriptBuilder)1 TransactionSigner (org.bitcoinj.signers.TransactionSigner)1 DecryptingKeyBag (org.bitcoinj.wallet.DecryptingKeyBag)1 KeyBag (org.bitcoinj.wallet.KeyBag)1 RedeemData (org.bitcoinj.wallet.RedeemData)1