use of io.bitsquare.btc.exceptions.TransactionVerificationException in project bitsquare by bitsquare.
the class TradeWalletService method takerSignsAndPublishesDepositTx.
/**
* The taker signs the deposit transaction he received from the offerer and publishes it.
*
* @param takerIsSeller The flag indicating if we are in the taker as seller role or the opposite.
* @param contractHash The hash of the contract to be added to the OP_RETURN output.
* @param offerersDepositTxSerialized The prepared deposit transaction signed by the offerer.
* @param buyerInputs The connected outputs for all inputs of the buyer.
* @param sellerInputs The connected outputs for all inputs of the seller.
* @param buyerPubKey The public key of the buyer.
* @param sellerPubKey The public key of the seller.
* @param arbitratorPubKey The public key of the arbitrator.
* @param callback Callback when transaction is broadcasted.
* @throws SigningException
* @throws TransactionVerificationException
* @throws WalletException
*/
public Transaction takerSignsAndPublishesDepositTx(boolean takerIsSeller, byte[] contractHash, byte[] offerersDepositTxSerialized, List<RawTransactionInput> buyerInputs, List<RawTransactionInput> sellerInputs, byte[] buyerPubKey, byte[] sellerPubKey, byte[] arbitratorPubKey, FutureCallback<Transaction> callback) throws SigningException, TransactionVerificationException, WalletException {
Transaction offerersDepositTx = new Transaction(params, offerersDepositTxSerialized);
log.trace("signAndPublishDepositTx called");
log.trace("takerIsSeller " + takerIsSeller);
log.trace("offerersDepositTx " + offerersDepositTx.toString());
log.trace("buyerConnectedOutputsForAllInputs " + buyerInputs.toString());
log.trace("sellerConnectedOutputsForAllInputs " + sellerInputs.toString());
log.trace("buyerPubKey " + ECKey.fromPublicOnly(buyerPubKey).toString());
log.trace("sellerPubKey " + ECKey.fromPublicOnly(sellerPubKey).toString());
log.trace("arbitratorPubKey " + ECKey.fromPublicOnly(arbitratorPubKey).toString());
checkArgument(!buyerInputs.isEmpty());
checkArgument(!sellerInputs.isEmpty());
// Check if offerer's Multisig script is identical to the takers
Script p2SHMultiSigOutputScript = getP2SHMultiSigOutputScript(buyerPubKey, sellerPubKey, arbitratorPubKey);
if (!offerersDepositTx.getOutput(0).getScriptPubKey().equals(p2SHMultiSigOutputScript))
throw new TransactionVerificationException("Offerer's p2SHMultiSigOutputScript does not match to takers p2SHMultiSigOutputScript");
// The outpoints are not available from the serialized offerersDepositTx, so we cannot use that tx directly, but we use it to construct a new
// depositTx
Transaction depositTx = new Transaction(params);
if (takerIsSeller) {
// We grab the signature from the offerersDepositTx and apply it to the new tx input
for (int i = 0; i < buyerInputs.size(); i++) depositTx.addInput(getTransactionInput(depositTx, getScriptProgram(offerersDepositTx, i), buyerInputs.get(i)));
// Add seller inputs
for (RawTransactionInput rawTransactionInput : sellerInputs) depositTx.addInput(getTransactionInput(depositTx, new byte[] {}, rawTransactionInput));
} else {
// Add buyer inputs and apply signature
for (RawTransactionInput rawTransactionInput : buyerInputs) depositTx.addInput(getTransactionInput(depositTx, new byte[] {}, rawTransactionInput));
// We grab the signature from the offerersDepositTx and apply it to the new tx input
for (int i = buyerInputs.size(), k = 0; i < offerersDepositTx.getInputs().size(); i++, k++) depositTx.addInput(getTransactionInput(depositTx, getScriptProgram(offerersDepositTx, i), sellerInputs.get(k)));
}
// Check if OP_RETURN output with contract hash matches the one from the offerer
TransactionOutput contractHashOutput = new TransactionOutput(params, offerersDepositTx, Coin.ZERO, ScriptBuilder.createOpReturnScript(contractHash).getProgram());
log.debug("contractHashOutput " + contractHashOutput);
TransactionOutput offerersContractHashOutput = offerersDepositTx.getOutputs().get(1);
log.debug("offerersContractHashOutput " + offerersContractHashOutput);
if (!offerersContractHashOutput.getScriptPubKey().equals(contractHashOutput.getScriptPubKey()))
throw new TransactionVerificationException("Offerer's transaction output for the contract hash is not matching takers version.");
// Add all outputs from offerersDepositTx to depositTx
offerersDepositTx.getOutputs().forEach(depositTx::addOutput);
//printTxWithInputs("offerersDepositTx", offerersDepositTx);
// Sign inputs
int start = takerIsSeller ? buyerInputs.size() : 0;
int end = takerIsSeller ? depositTx.getInputs().size() : buyerInputs.size();
for (int i = start; i < end; i++) {
TransactionInput input = depositTx.getInput(i);
signInput(depositTx, input, i);
checkScriptSig(depositTx, input, i);
}
printTxWithInputs("depositTx", depositTx);
verifyTransaction(depositTx);
checkWalletConsistency();
// Broadcast depositTx
checkNotNull(walletAppKit);
ListenableFuture<Transaction> broadcastComplete = walletAppKit.peerGroup().broadcastTransaction(depositTx).future();
Futures.addCallback(broadcastComplete, callback);
return depositTx;
}
Aggregations