All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bitcoinj.signers.CustomTransactionSigner Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2014 Kosta Korenkov
 * Copyright 2019 Andreas Schildbach
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.bitcoinj.signers;

import org.bitcoinj.core.*;
import org.bitcoinj.crypto.ChildNumber;
import org.bitcoinj.crypto.TransactionSignature;
import org.bitcoinj.script.Script;
import org.bitcoinj.script.ScriptException;
import org.bitcoinj.script.ScriptPattern;
import org.bitcoinj.wallet.KeyBag;
import org.bitcoinj.wallet.RedeemData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * 

This signer may be used as a template for creating custom multisig transaction signers.

*

* Concrete implementations have to implement {@link #getSignature(Sha256Hash, List)} * method returning a signature and a public key of the keypair used to created that signature. * It's up to custom implementation where to locate signatures: it may be a network connection, * some local API or something else. *

*/ public abstract class CustomTransactionSigner implements TransactionSigner { private static final Logger log = LoggerFactory.getLogger(CustomTransactionSigner.class); @Override public boolean isReady() { return true; } @Override public boolean signInputs(ProposedTransaction propTx, KeyBag keyBag) { Transaction tx = propTx.partialTx; int numInputs = tx.getInputs().size(); for (int i = 0; i < numInputs; i++) { TransactionInput txIn = tx.getInput(i); TransactionOutput txOut = txIn.getConnectedOutput(); if (txOut == null) { continue; } Script scriptPubKey = txOut.getScriptPubKey(); if (!ScriptPattern.isP2SH(scriptPubKey)) { log.warn("CustomTransactionSigner works only with P2SH transactions"); return false; } Script inputScript = checkNotNull(txIn.getScriptSig()); 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, i, txOut.getScriptPubKey(), Script.ALL_VERIFY_FLAGS); log.warn("Input {} already correctly spends output, assuming SIGHASH type used will be safe and skipping signing.", i); continue; } catch (ScriptException e) { // Expected. } RedeemData redeemData = txIn.getConnectedRedeemData(keyBag); if (redeemData == null) { log.warn("No redeem data found for input {}", i); continue; } Sha256Hash sighash = tx.hashForSignature(i, redeemData.redeemScript, Transaction.SigHash.ALL, false); SignatureAndKey sigKey = getSignature(sighash, propTx.keyPaths.get(scriptPubKey)); TransactionSignature txSig = new TransactionSignature(sigKey.sig, Transaction.SigHash.ALL, false); int sigIndex = inputScript.getSigInsertionIndex(sighash, sigKey.pubKey); inputScript = scriptPubKey.getScriptSigWithSignature(inputScript, txSig.encodeToBitcoin(), sigIndex); txIn.setScriptSig(inputScript); } return true; } protected abstract SignatureAndKey getSignature(Sha256Hash sighash, List derivationPath); public class SignatureAndKey { public final ECKey.ECDSASignature sig; public final ECKey pubKey; public SignatureAndKey(ECKey.ECDSASignature sig, ECKey pubKey) { this.sig = sig; this.pubKey = pubKey; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy