use of io.bitsquare.btc.data.PreparedDepositTxAndOffererInputs in project bitsquare by bitsquare.
the class TradeWalletService method offererCreatesAndSignsDepositTx.
/**
* The offerer creates the deposit transaction using the takers input(s) and optional output and signs his input(s).
*
* @param offererIsBuyer The flag indicating if we are in the offerer as buyer role or the opposite.
* @param contractHash The hash of the contract to be added to the OP_RETURN output.
* @param offererInputAmount The input amount of the offerer.
* @param msOutputAmount The output amount to our MS output.
* @param takerRawTransactionInputs Raw data for the connected outputs for all inputs of the taker (normally 1 input)
* @param takerChangeOutputValue Optional taker change output value
* @param takerChangeAddressString Optional taker change address
* @param offererAddress The offerer's address.
* @param offererChangeAddress The offerer's change address.
* @param buyerPubKey The public key of the buyer.
* @param sellerPubKey The public key of the seller.
* @param arbitratorPubKey The public key of the arbitrator.
* @return A data container holding the serialized transaction and the offerer raw inputs
* @throws SigningException
* @throws TransactionVerificationException
* @throws WalletException
*/
public PreparedDepositTxAndOffererInputs offererCreatesAndSignsDepositTx(boolean offererIsBuyer, byte[] contractHash, Coin offererInputAmount, Coin msOutputAmount, List<RawTransactionInput> takerRawTransactionInputs, long takerChangeOutputValue, @Nullable String takerChangeAddressString, Address offererAddress, Address offererChangeAddress, byte[] buyerPubKey, byte[] sellerPubKey, byte[] arbitratorPubKey) throws SigningException, TransactionVerificationException, WalletException, AddressFormatException {
log.trace("offererCreatesAndSignsDepositTx called");
log.trace("offererIsBuyer " + offererIsBuyer);
log.trace("offererInputAmount " + offererInputAmount.toFriendlyString());
log.trace("msOutputAmount " + msOutputAmount.toFriendlyString());
log.trace("takerRawInputs " + takerRawTransactionInputs.toString());
log.trace("takerChangeOutputValue " + takerChangeOutputValue);
log.trace("takerChangeAddressString " + takerChangeAddressString);
log.trace("offererAddress " + offererAddress);
log.trace("offererChangeAddress " + offererChangeAddress);
log.trace("buyerPubKey " + ECKey.fromPublicOnly(buyerPubKey).toString());
log.trace("sellerPubKey " + ECKey.fromPublicOnly(sellerPubKey).toString());
log.trace("arbitratorPubKey " + ECKey.fromPublicOnly(arbitratorPubKey).toString());
checkArgument(!takerRawTransactionInputs.isEmpty());
// First we construct a dummy TX to get the inputs and outputs we want to use for the real deposit tx.
// Similar to the way we did in the createTakerDepositTxInputs method.
Transaction dummyTx = new Transaction(params);
Coin dummyOutputAmount = offererInputAmount.subtract(FeePolicy.getFixedTxFeeForTrades());
TransactionOutput dummyOutput = new TransactionOutput(params, dummyTx, dummyOutputAmount, new ECKey().toAddress(params));
dummyTx.addOutput(dummyOutput);
addAvailableInputsAndChangeOutputs(dummyTx, offererAddress, offererChangeAddress);
// Normally we have only 1 input but we support multiple inputs if the user has paid in with several transactions.
List<TransactionInput> offererInputs = dummyTx.getInputs();
TransactionOutput offererOutput = null;
// We don't support more then 1 optional change output
Preconditions.checkArgument(dummyTx.getOutputs().size() < 3, "dummyTx.getOutputs().size() >= 3");
// Only save change outputs, the dummy output is ignored (that's why we start with index 1)
if (dummyTx.getOutputs().size() > 1)
offererOutput = dummyTx.getOutput(1);
// Now we construct the real deposit tx
Transaction preparedDepositTx = new Transaction(params);
ArrayList<RawTransactionInput> offererRawTransactionInputs = new ArrayList<>();
if (offererIsBuyer) {
// Add buyer inputs
for (TransactionInput input : offererInputs) {
preparedDepositTx.addInput(input);
offererRawTransactionInputs.add(getRawInputFromTransactionInput(input));
}
// the sellers input is not signed so we attach empty script bytes
for (RawTransactionInput rawTransactionInput : takerRawTransactionInputs) preparedDepositTx.addInput(getTransactionInput(preparedDepositTx, new byte[] {}, rawTransactionInput));
} else {
// the sellers input is not signed so we attach empty script bytes
for (RawTransactionInput rawTransactionInput : takerRawTransactionInputs) preparedDepositTx.addInput(getTransactionInput(preparedDepositTx, new byte[] {}, rawTransactionInput));
// Add seller inputs
for (TransactionInput input : offererInputs) {
preparedDepositTx.addInput(input);
offererRawTransactionInputs.add(getRawInputFromTransactionInput(input));
}
}
// Add MultiSig output
Script p2SHMultiSigOutputScript = getP2SHMultiSigOutputScript(buyerPubKey, sellerPubKey, arbitratorPubKey);
// Tx fee for deposit tx will be paid by buyer.
TransactionOutput p2SHMultiSigOutput = new TransactionOutput(params, preparedDepositTx, msOutputAmount, p2SHMultiSigOutputScript.getProgram());
preparedDepositTx.addOutput(p2SHMultiSigOutput);
// We add the hash ot OP_RETURN with a 0 amount output
TransactionOutput contractHashOutput = new TransactionOutput(params, preparedDepositTx, Coin.ZERO, ScriptBuilder.createOpReturnScript(contractHash).getProgram());
preparedDepositTx.addOutput(contractHashOutput);
TransactionOutput takerTransactionOutput = null;
if (takerChangeOutputValue > 0 && takerChangeAddressString != null)
takerTransactionOutput = new TransactionOutput(params, preparedDepositTx, Coin.valueOf(takerChangeOutputValue), new Address(params, takerChangeAddressString));
if (offererIsBuyer) {
// Add optional buyer outputs
if (offererOutput != null)
preparedDepositTx.addOutput(offererOutput);
// Add optional seller outputs
if (takerTransactionOutput != null)
preparedDepositTx.addOutput(takerTransactionOutput);
} else {
// Add optional seller outputs
if (takerTransactionOutput != null)
preparedDepositTx.addOutput(takerTransactionOutput);
// Add optional buyer outputs
if (offererOutput != null)
preparedDepositTx.addOutput(offererOutput);
}
// Sign inputs
int start = offererIsBuyer ? 0 : takerRawTransactionInputs.size();
int end = offererIsBuyer ? offererInputs.size() : preparedDepositTx.getInputs().size();
for (int i = start; i < end; i++) {
TransactionInput input = preparedDepositTx.getInput(i);
signInput(preparedDepositTx, input, i);
checkScriptSig(preparedDepositTx, input, i);
}
verifyTransaction(preparedDepositTx);
return new PreparedDepositTxAndOffererInputs(offererRawTransactionInputs, preparedDepositTx.bitcoinSerialize());
}
use of io.bitsquare.btc.data.PreparedDepositTxAndOffererInputs in project bitsquare by bitsquare.
the class OffererCreatesAndSignsDepositTxAsBuyer method run.
@Override
protected void run() {
try {
runInterceptHook();
checkNotNull(trade.getTradeAmount(), "trade.getTradeAmount() must not be null");
Offer offer = trade.getOffer();
Coin securityDeposit = FeePolicy.getSecurityDeposit(offer);
Coin buyerInputAmount = securityDeposit.add(FeePolicy.getFixedTxFeeForTrades(offer));
Coin msOutputAmount = buyerInputAmount.add(securityDeposit).add(trade.getTradeAmount());
log.debug("\n\n------------------------------------------------------------\n" + "Contract as json\n" + trade.getContractAsJson() + "\n------------------------------------------------------------\n");
byte[] contractHash = Hash.getHash(trade.getContractAsJson());
trade.setContractHash(contractHash);
WalletService walletService = processModel.getWalletService();
String id = processModel.getOffer().getId();
AddressEntry offererAddressEntry = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.RESERVED_FOR_TRADE);
AddressEntry buyerMultiSigAddressEntry = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.MULTI_SIG);
buyerMultiSigAddressEntry.setCoinLockedInMultiSig(buyerInputAmount.subtract(FeePolicy.getFixedTxFeeForTrades(offer)));
Address changeAddress = walletService.getOrCreateAddressEntry(AddressEntry.Context.AVAILABLE).getAddress();
PreparedDepositTxAndOffererInputs result = processModel.getTradeWalletService().offererCreatesAndSignsDepositTx(true, contractHash, buyerInputAmount, msOutputAmount, processModel.tradingPeer.getRawTransactionInputs(), processModel.tradingPeer.getChangeOutputValue(), processModel.tradingPeer.getChangeOutputAddress(), offererAddressEntry.getAddress(), changeAddress, buyerMultiSigAddressEntry.getPubKey(), processModel.tradingPeer.getMultiSigPubKey(), trade.getArbitratorPubKey());
processModel.setPreparedDepositTx(result.depositTransaction);
processModel.setRawTransactionInputs(result.rawOffererInputs);
complete();
} catch (Throwable t) {
failed(t);
}
}
use of io.bitsquare.btc.data.PreparedDepositTxAndOffererInputs in project bitsquare by bitsquare.
the class OffererCreatesAndSignsDepositTxAsSeller method run.
@Override
protected void run() {
try {
runInterceptHook();
checkNotNull(trade.getTradeAmount(), "trade.getTradeAmount() must not be null");
Offer offer = trade.getOffer();
Coin sellerInputAmount = FeePolicy.getSecurityDeposit(offer).add(FeePolicy.getFixedTxFeeForTrades(offer)).add(trade.getTradeAmount());
Coin msOutputAmount = sellerInputAmount.add(FeePolicy.getSecurityDeposit(offer));
log.debug("\n\n------------------------------------------------------------\n" + "Contract as json\n" + trade.getContractAsJson() + "\n------------------------------------------------------------\n");
byte[] contractHash = Hash.getHash(trade.getContractAsJson());
trade.setContractHash(contractHash);
WalletService walletService = processModel.getWalletService();
String id = processModel.getOffer().getId();
AddressEntry offererAddressEntry = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.RESERVED_FOR_TRADE);
AddressEntry sellerMultiSigAddressEntry = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.MULTI_SIG);
sellerMultiSigAddressEntry.setCoinLockedInMultiSig(sellerInputAmount.subtract(FeePolicy.getFixedTxFeeForTrades(offer)));
Address changeAddress = walletService.getOrCreateAddressEntry(AddressEntry.Context.AVAILABLE).getAddress();
PreparedDepositTxAndOffererInputs result = processModel.getTradeWalletService().offererCreatesAndSignsDepositTx(false, contractHash, sellerInputAmount, msOutputAmount, processModel.tradingPeer.getRawTransactionInputs(), processModel.tradingPeer.getChangeOutputValue(), processModel.tradingPeer.getChangeOutputAddress(), offererAddressEntry.getAddress(), changeAddress, processModel.tradingPeer.getMultiSigPubKey(), sellerMultiSigAddressEntry.getPubKey(), trade.getArbitratorPubKey());
processModel.setPreparedDepositTx(result.depositTransaction);
processModel.setRawTransactionInputs(result.rawOffererInputs);
complete();
} catch (Throwable t) {
failed(t);
}
}
Aggregations