Java Code Examples for org.bitcoinj.core.Transaction#addInput()

The following examples show how to use org.bitcoinj.core.Transaction#addInput() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: WalletTest.java    From green_android with GNU General Public License v3.0 6 votes vote down vote up
@Test
public void replayWhilstPending() throws Exception {
    // Check that if a pending transaction spends outputs of chain-included transactions, we mark them as spent.
    // See bug 345. This can happen if there is a pending transaction floating around and then you replay the
    // chain without emptying the memory pool (or refilling it from a peer).
    Coin value = COIN;
    Transaction tx1 = createFakeTx(PARAMS, value, myAddress);
    Transaction tx2 = new Transaction(PARAMS);
    tx2.addInput(tx1.getOutput(0));
    tx2.addOutput(valueOf(0, 9), OTHER_ADDRESS);
    // Add a change address to ensure this tx is relevant.
    tx2.addOutput(CENT, wallet.currentChangeAddress());
    wallet.receivePending(tx2, null);
    sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, tx1);
    assertEquals(ZERO, wallet.getBalance());
    assertEquals(1, wallet.getPoolSize(Pool.SPENT));
    assertEquals(1, wallet.getPoolSize(Pool.PENDING));
    assertEquals(0, wallet.getPoolSize(Pool.UNSPENT));
}
 
Example 2
Source File: SendRequest.java    From bcm-android with GNU General Public License v3.0 6 votes vote down vote up
/**
 * Construct a SendRequest for a CPFP (child-pays-for-parent) transaction. The resulting transaction is already
 * completed, so you should directly proceed to signing and broadcasting/committing the transaction. CPFP is
 * currently only supported by a few miners, so use with care.
 */
public static SendRequest childPaysForParent(Wallet wallet, Transaction parentTransaction, Coin feeRaise) {
    TransactionOutput outputToSpend = null;
    for (final TransactionOutput output : parentTransaction.getOutputs()) {
        if (output.isMine(wallet) && output.isAvailableForSpending()
                && output.getValue().isGreaterThan(feeRaise)) {
            outputToSpend = output;
            break;
        }
    }
    // TODO spend another confirmed output of own wallet if needed
    checkNotNull(outputToSpend, "Can't find adequately sized output that spends to us");

    final Transaction tx = new Transaction(parentTransaction.getParams());
    tx.addInput(outputToSpend);
    tx.addOutput(outputToSpend.getValue().subtract(feeRaise), wallet.freshAddress(KeyPurpose.CHANGE));
    tx.setPurpose(Transaction.Purpose.RAISE_FEE);
    final SendRequest req = forTx(tx);
    req.completed = true;
    return req;
}
 
Example 3
Source File: ToolsTest.java    From thunder with GNU Affero General Public License v3.0 6 votes vote down vote up
private static Transaction shuffleTransaction (Transaction transaction) {
    Transaction shuffledTransaction = new Transaction(Constants.getNetwork());

    List<TransactionInput> shuffledInputs = new ArrayList<>(transaction.getInputs());
    List<TransactionOutput> shuffledOutputs = new ArrayList<>(transaction.getOutputs());

    Collections.shuffle(shuffledInputs);
    Collections.shuffle(shuffledOutputs);
    for (TransactionInput input : shuffledInputs) {
        shuffledTransaction.addInput(input);
    }
    for (TransactionOutput output : shuffledOutputs) {
        shuffledTransaction.addOutput(output);
    }
    return shuffledTransaction;
}
 
Example 4
Source File: WalletTest.java    From green_android with GNU General Public License v3.0 6 votes vote down vote up
@Test
public void watchingScriptsSentFrom() throws Exception {
    int baseElements = wallet.getBloomFilterElementCount();

    Address watchedAddress = new ECKey().toAddress(PARAMS);
    wallet.addWatchedAddress(watchedAddress);
    assertEquals(baseElements + 1, wallet.getBloomFilterElementCount());

    Transaction t1 = createFakeTx(PARAMS, CENT, watchedAddress);
    Transaction t2 = createFakeTx(PARAMS, COIN, OTHER_ADDRESS);
    sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, t1);
    assertEquals(baseElements + 2, wallet.getBloomFilterElementCount());
    Transaction st2 = new Transaction(PARAMS);
    st2.addOutput(CENT, OTHER_ADDRESS);
    st2.addOutput(COIN, OTHER_ADDRESS);
    st2.addInput(t1.getOutput(0));
    st2.addInput(t2.getOutput(0));
    sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, st2);
    assertEquals(baseElements + 2, wallet.getBloomFilterElementCount());
    assertEquals(CENT, st2.getValueSentFromMe(wallet));
}
 
Example 5
Source File: WalletTest.java    From green_android with GNU General Public License v3.0 6 votes vote down vote up
@Test
public void bounce() throws Exception {
    // This test covers bug 64 (False double spends). Check that if we create a spend and it's immediately sent
    // back to us, this isn't considered as a double spend.
    Coin coin1 = COIN;
    sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, coin1);
    // Send half to some other guy. Sending only half then waiting for a confirm is important to ensure the tx is
    // in the unspent pool, not pending or spent.
    Coin coinHalf = valueOf(0, 50);
    assertEquals(1, wallet.getPoolSize(WalletTransaction.Pool.UNSPENT));
    assertEquals(1, wallet.getTransactions(true).size());
    Transaction outbound1 = wallet.createSend(OTHER_ADDRESS, coinHalf);
    wallet.commitTx(outbound1);
    sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, outbound1);
    assertTrue(outbound1.getWalletOutputs(wallet).size() <= 1); //the change address at most
    // That other guy gives us the coins right back.
    Transaction inbound2 = new Transaction(PARAMS);
    inbound2.addOutput(new TransactionOutput(PARAMS, inbound2, coinHalf, myAddress));
    assertTrue(outbound1.getWalletOutputs(wallet).size() >= 1);
    inbound2.addInput(outbound1.getOutputs().get(0));
    sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, inbound2);
    assertEquals(coin1, wallet.getBalance());
}
 
Example 6
Source File: FakeTxBuilder.java    From bcm-android with GNU General Public License v3.0 6 votes vote down vote up
/**
 * Create a fake TX of sufficient realism to exercise the unit tests. Two outputs, one to us, one to somewhere
 * else to simulate change. There is one random input.
 */
public static Transaction createFakeTx(NetworkParameters params, Coin value, ECKey to) {
    Transaction t = new Transaction(params);
    TransactionOutput outputToMe = new TransactionOutput(params, t, value, to);
    t.addOutput(outputToMe);
    TransactionOutput change = new TransactionOutput(params, t, valueOf(1, 11), new ECKey());
    t.addOutput(change);
    // Make a previous tx simply to send us sufficient coins. This prev tx is not really valid but it doesn't
    // matter for our purposes.
    Transaction prevTx = new Transaction(params);
    TransactionOutput prevOut = new TransactionOutput(params, prevTx, value, to);
    prevTx.addOutput(prevOut);
    // Connect it.
    t.addInput(prevOut);
    // Serialize/deserialize to ensure internal state is stripped, as if it had been read from the wire.
    return roundTripTransaction(params, t);
}
 
Example 7
Source File: TradeWalletService.java    From bisq-core with GNU Affero General Public License v3.0 5 votes vote down vote up
private Transaction createPayoutTx(Transaction depositTx,
                                   Coin buyerPayoutAmount,
                                   Coin sellerPayoutAmount,
                                   String buyerAddressString,
                                   String sellerAddressString) throws AddressFormatException {
    TransactionOutput p2SHMultiSigOutput = depositTx.getOutput(0);
    Transaction transaction = new Transaction(params);
    transaction.addInput(p2SHMultiSigOutput);
    transaction.addOutput(buyerPayoutAmount, Address.fromBase58(params, buyerAddressString));
    transaction.addOutput(sellerPayoutAmount, Address.fromBase58(params, sellerAddressString));
    return transaction;
}
 
Example 8
Source File: BsqWalletService.java    From bisq with GNU Affero General Public License v3.0 5 votes vote down vote up
public Transaction getPreparedVoteRevealTx(TxOutput stakeTxOutput) {
    daoKillSwitch.assertDaoIsNotDisabled();
    Transaction tx = new Transaction(params);
    final Coin stake = Coin.valueOf(stakeTxOutput.getValue());
    Transaction blindVoteTx = getTransaction(stakeTxOutput.getTxId());
    checkNotNull(blindVoteTx, "blindVoteTx must not be null");
    TransactionOutPoint outPoint = new TransactionOutPoint(params, stakeTxOutput.getIndex(), blindVoteTx);
    // Input is not signed yet so we use new byte[]{}
    tx.addInput(new TransactionInput(params, tx, new byte[]{}, outPoint, stake));
    tx.addOutput(new TransactionOutput(params, tx, stake, getUnusedAddress()));
    // printTx("getPreparedVoteRevealTx", tx);
    return tx;
}
 
Example 9
Source File: LNPaymentMessageFactoryMock.java    From thunder with GNU Affero General Public License v3.0 5 votes vote down vote up
private List<TransactionSignature> getMockSig () {
    ECKey k = new ECKey();
    Transaction t = new Transaction(Constants.getNetwork());
    t.addInput(Sha256Hash.ZERO_HASH, 0, Tools.getDummyScript());
    t.addOutput(Coin.ZERO, Tools.getDummyScript());

    return Collections.singletonList(Tools.getSignature(t, 0, t.getOutput(0),k));
}
 
Example 10
Source File: BsqWalletService.java    From bisq-core with GNU Affero General Public License v3.0 5 votes vote down vote up
public Transaction getPreparedUnlockTx(TxOutput lockedTxOutput) throws AddressFormatException {
    Transaction tx = new Transaction(params);
    // Unlocking means spending the full value of the locked txOutput to another txOutput with the same value
    Coin amountToUnlock = Coin.valueOf(lockedTxOutput.getValue());
    checkArgument(Restrictions.isAboveDust(amountToUnlock), "The amount is too low (dust limit).");
    Transaction lockupTx = getTransaction(lockedTxOutput.getTxId());
    checkNotNull(lockupTx, "lockupTx must not be null");
    TransactionOutPoint outPoint = new TransactionOutPoint(params, lockedTxOutput.getIndex(), lockupTx);
    // Input is not signed yet so we use new byte[]{}
    tx.addInput(new TransactionInput(params, tx, new byte[]{}, outPoint, amountToUnlock));
    tx.addOutput(new TransactionOutput(params, tx, amountToUnlock, getUnusedAddress()));
    printTx("prepareUnlockTx", tx);
    return tx;
}
 
Example 11
Source File: BsqWalletService.java    From bisq-core with GNU Affero General Public License v3.0 5 votes vote down vote up
public Transaction getPreparedVoteRevealTx(TxOutput stakeTxOutput) {
    Transaction tx = new Transaction(params);
    final Coin stake = Coin.valueOf(stakeTxOutput.getValue());
    Transaction blindVoteTx = getTransaction(stakeTxOutput.getTxId());
    checkNotNull(blindVoteTx, "blindVoteTx must not be null");
    TransactionOutPoint outPoint = new TransactionOutPoint(params, stakeTxOutput.getIndex(), blindVoteTx);
    // Input is not signed yet so we use new byte[]{}
    tx.addInput(new TransactionInput(params, tx, new byte[]{}, outPoint, stake));
    tx.addOutput(new TransactionOutput(params, tx, stake, getUnusedAddress()));
    // printTx("getPreparedVoteRevealTx", tx);
    return tx;
}
 
Example 12
Source File: FakeTxBuilder.java    From bcm-android with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Transaction[0] is a feeder transaction, supplying BTC to Transaction[1]
 */
public static Transaction[] createFakeTx(NetworkParameters params, Coin value,
                                         Address to, Address from) {
    // Create fake TXes of sufficient realism to exercise the unit tests. This transaction send BTC from the
    // from address, to the to address with to one to somewhere else to simulate change.
    Transaction t = new Transaction(params);
    TransactionOutput outputToMe = new TransactionOutput(params, t, value, to);
    t.addOutput(outputToMe);
    TransactionOutput change = new TransactionOutput(params, t, valueOf(1, 11), LegacyAddress.fromKey(params, new ECKey()));
    t.addOutput(change);
    // Make a feeder tx that sends to the from address specified. This feeder tx is not really valid but it doesn't
    // matter for our purposes.
    Transaction feederTx = new Transaction(params);
    TransactionOutput feederOut = new TransactionOutput(params, feederTx, value, from);
    feederTx.addOutput(feederOut);

    // make a previous tx that sends from the feeder to the from address
    Transaction prevTx = new Transaction(params);
    TransactionOutput prevOut = new TransactionOutput(params, prevTx, value, to);
    prevTx.addOutput(prevOut);

    // Connect up the txes
    prevTx.addInput(feederOut);
    t.addInput(prevOut);

    // roundtrip the tx so that they are just like they would be from the wire
    return new Transaction[]{roundTripTransaction(params, prevTx), roundTripTransaction(params, t)};
}
 
Example 13
Source File: FakeTxBuilder.java    From bcm-android with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Create a fake coinbase transaction.
 */
public static Transaction createFakeCoinbaseTx(final NetworkParameters params) {
    TransactionOutPoint outpoint = new TransactionOutPoint(params, -1, Sha256Hash.ZERO_HASH);
    TransactionInput input = new TransactionInput(params, null, new byte[0], outpoint);
    Transaction tx = new Transaction(params);
    tx.addInput(input);
    TransactionOutput outputToMe = new TransactionOutput(params, tx, Coin.FIFTY_COINS,
            LegacyAddress.fromKey(params, new ECKey()));
    tx.addOutput(outputToMe);

    checkState(tx.isCoinBase());
    return tx;
}
 
Example 14
Source File: FakeTxBuilder.java    From bcm-android with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Create a fake transaction, without change.
 */
public static Transaction createFakeTxWithoutChange(final NetworkParameters params, final TransactionOutput output) {
    Transaction prevTx = FakeTxBuilder.createFakeTx(params, Coin.COIN, LegacyAddress.fromKey(params, new ECKey()));
    Transaction tx = new Transaction(params);
    tx.addOutput(output);
    tx.addInput(prevTx.getOutput(0));
    return tx;
}
 
Example 15
Source File: WalletTest.java    From bcm-android with GNU General Public License v3.0 5 votes vote down vote up
@Test
public void testIrrelevantDoubleSpend() throws Exception {
    Transaction tx0 = createFakeTx(UNITTEST);
    Transaction tx1 = createFakeTx(UNITTEST);

    Transaction tx2 = new Transaction(UNITTEST);
    tx2.addInput(tx0.getOutput(0));
    tx2.addOutput(COIN, myAddress);
    tx2.addOutput(COIN, OTHER_ADDRESS);

    sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, tx2, tx1, tx0);

    // tx3 and tx4 double spend each other
    Transaction tx3 = new Transaction(UNITTEST);
    tx3.addInput(tx1.getOutput(0));
    tx3.addOutput(COIN, myAddress);
    tx3.addOutput(COIN, OTHER_ADDRESS);
    wallet.receivePending(tx3, null);

    // tx4 also spends irrelevant output from tx2
    Transaction tx4 = new Transaction(UNITTEST);
    tx4.addInput(tx1.getOutput(0)); // spends same output
    tx4.addInput(tx2.getOutput(1));
    tx4.addOutput(COIN, OTHER_ADDRESS);

    // tx4 does not actually get added to wallet here since it by itself is irrelevant
    sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, tx4);

    // since tx4 is not saved, tx2 output 1 will have bad spentBy
    wallet = roundTrip(wallet);

    assertTrue(wallet.isConsistent());
}
 
Example 16
Source File: WalletTest.java    From green_android with GNU General Public License v3.0 5 votes vote down vote up
@Test
public void doubleSpendWeReceive() throws Exception {
    FakeTxBuilder.DoubleSpends doubleSpends = FakeTxBuilder.createFakeDoubleSpendTxns(PARAMS, myAddress);
    // doubleSpends.t1 spends to our wallet. doubleSpends.t2 double spends somewhere else.

    Transaction t1b = new Transaction(PARAMS);
    TransactionOutput t1bo = new TransactionOutput(PARAMS, t1b, valueOf(0, 50), OTHER_ADDRESS);
    t1b.addOutput(t1bo);
    t1b.addInput(doubleSpends.t1.getOutput(0));

    wallet.receivePending(doubleSpends.t1, null);
    wallet.receivePending(doubleSpends.t2, null);
    wallet.receivePending(t1b, null);
    assertInConflict(doubleSpends.t1);
    assertInConflict(doubleSpends.t1);
    assertInConflict(t1b);

    // Add a block to the block store. The rest of the blocks in this test will be on top of this one.
    FakeTxBuilder.BlockPair blockPair0 = createFakeBlock(blockStore, 1);

    // A block was mined including doubleSpends.t1
    FakeTxBuilder.BlockPair blockPair1 = createFakeBlock(blockStore, 2, doubleSpends.t1);
    wallet.receiveFromBlock(doubleSpends.t1, blockPair1.storedBlock, AbstractBlockChain.NewBlockType.BEST_CHAIN, 0);
    wallet.notifyNewBestBlock(blockPair1.storedBlock);
    assertSpent(doubleSpends.t1);
    assertDead(doubleSpends.t2);
    assertPending(t1b);

    // A reorg: previous block "replaced" by new block containing doubleSpends.t2
    FakeTxBuilder.BlockPair blockPair2 = createFakeBlock(blockStore, blockPair0.storedBlock, 2, doubleSpends.t2);
    wallet.receiveFromBlock(doubleSpends.t2, blockPair2.storedBlock, AbstractBlockChain.NewBlockType.SIDE_CHAIN, 0);
    wallet.reorganize(blockPair0.storedBlock, Lists.newArrayList(blockPair1.storedBlock),
            Lists.newArrayList(blockPair2.storedBlock));
    assertDead(doubleSpends.t1);
    assertSpent(doubleSpends.t2);
    assertDead(t1b);
}
 
Example 17
Source File: WalletTest.java    From bcm-android with GNU General Public License v3.0 5 votes vote down vote up
@Test
public void spendOutputFromPendingTransaction() throws Exception {
    // We'll set up a wallet that receives a coin, then sends a coin of lesser value and keeps the change.
    Coin v1 = COIN;
    sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, v1);
    // First create our current transaction
    ECKey k2 = wallet.freshReceiveKey();
    Coin v2 = valueOf(0, 50);
    Transaction t2 = new Transaction(UNITTEST);
    TransactionOutput o2 = new TransactionOutput(UNITTEST, t2, v2, LegacyAddress.fromKey(UNITTEST, k2));
    t2.addOutput(o2);
    SendRequest req = SendRequest.forTx(t2);
    wallet.completeTx(req);

    // Commit t2, so it is placed in the pending pool
    wallet.commitTx(t2);
    assertEquals(0, wallet.getPoolSize(WalletTransaction.Pool.UNSPENT));
    assertEquals(1, wallet.getPoolSize(WalletTransaction.Pool.PENDING));
    assertEquals(2, wallet.getTransactions(true).size());

    // Now try to the spend the output.
    ECKey k3 = new ECKey();
    Coin v3 = valueOf(0, 25);
    Transaction t3 = new Transaction(UNITTEST);
    t3.addOutput(v3, LegacyAddress.fromKey(UNITTEST, k3));
    t3.addInput(o2);
    wallet.signTransaction(SendRequest.forTx(t3));

    // Commit t3, so the coins from the pending t2 are spent
    wallet.commitTx(t3);
    assertEquals(0, wallet.getPoolSize(WalletTransaction.Pool.UNSPENT));
    assertEquals(2, wallet.getPoolSize(WalletTransaction.Pool.PENDING));
    assertEquals(3, wallet.getTransactions(true).size());

    // Now the output of t2 must not be available for spending
    assertFalse(o2.isAvailableForSpending());
}
 
Example 18
Source File: WalletTest.java    From GreenBits with GNU General Public License v3.0 5 votes vote down vote up
@Test
public void doubleSpendWeReceive() throws Exception {
    FakeTxBuilder.DoubleSpends doubleSpends = FakeTxBuilder.createFakeDoubleSpendTxns(PARAMS, myAddress);
    // doubleSpends.t1 spends to our wallet. doubleSpends.t2 double spends somewhere else.

    Transaction t1b = new Transaction(PARAMS);
    TransactionOutput t1bo = new TransactionOutput(PARAMS, t1b, valueOf(0, 50), OTHER_ADDRESS);
    t1b.addOutput(t1bo);
    t1b.addInput(doubleSpends.t1.getOutput(0));

    wallet.receivePending(doubleSpends.t1, null);
    wallet.receivePending(doubleSpends.t2, null);
    wallet.receivePending(t1b, null);
    assertInConflict(doubleSpends.t1);
    assertInConflict(doubleSpends.t1);
    assertInConflict(t1b);

    // Add a block to the block store. The rest of the blocks in this test will be on top of this one.
    FakeTxBuilder.BlockPair blockPair0 = createFakeBlock(blockStore, 1);

    // A block was mined including doubleSpends.t1
    FakeTxBuilder.BlockPair blockPair1 = createFakeBlock(blockStore, 2, doubleSpends.t1);
    wallet.receiveFromBlock(doubleSpends.t1, blockPair1.storedBlock, AbstractBlockChain.NewBlockType.BEST_CHAIN, 0);
    wallet.notifyNewBestBlock(blockPair1.storedBlock);
    assertSpent(doubleSpends.t1);
    assertDead(doubleSpends.t2);
    assertPending(t1b);

    // A reorg: previous block "replaced" by new block containing doubleSpends.t2
    FakeTxBuilder.BlockPair blockPair2 = createFakeBlock(blockStore, blockPair0.storedBlock, 2, doubleSpends.t2);
    wallet.receiveFromBlock(doubleSpends.t2, blockPair2.storedBlock, AbstractBlockChain.NewBlockType.SIDE_CHAIN, 0);
    wallet.reorganize(blockPair0.storedBlock, Lists.newArrayList(blockPair1.storedBlock),
            Lists.newArrayList(blockPair2.storedBlock));
    assertDead(doubleSpends.t1);
    assertSpent(doubleSpends.t2);
    assertDead(t1b);
}
 
Example 19
Source File: TradeWalletService.java    From bisq with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * A trader who got the signed tx from the arbitrator finalizes the payout tx.
 *
 * @param depositTxSerialized    serialized deposit tx
 * @param arbitratorSignature    DER encoded canonical signature of arbitrator
 * @param buyerPayoutAmount      payout amount of the buyer
 * @param sellerPayoutAmount     payout amount of the seller
 * @param buyerAddressString     the address of the buyer
 * @param sellerAddressString    the address of the seller
 * @param tradersMultiSigKeyPair the key pair for the MultiSig of the trader who calls that method
 * @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 the completed payout tx
 * @throws AddressFormatException if the buyer or seller base58 address doesn't parse or its checksum is invalid
 * @throws TransactionVerificationException if there was an unexpected problem with the payout tx or its signature
 * @throws WalletException if the trade wallet is null or structurally inconsistent
 */
public Transaction traderSignAndFinalizeDisputedPayoutTx(byte[] depositTxSerialized,
                                                         byte[] arbitratorSignature,
                                                         Coin buyerPayoutAmount,
                                                         Coin sellerPayoutAmount,
                                                         String buyerAddressString,
                                                         String sellerAddressString,
                                                         DeterministicKey tradersMultiSigKeyPair,
                                                         byte[] buyerPubKey,
                                                         byte[] sellerPubKey,
                                                         byte[] arbitratorPubKey)
        throws AddressFormatException, TransactionVerificationException, WalletException {
    Transaction depositTx = new Transaction(params, depositTxSerialized);
    TransactionOutput p2SHMultiSigOutput = depositTx.getOutput(0);
    Transaction payoutTx = new Transaction(params);
    payoutTx.addInput(p2SHMultiSigOutput);
    if (buyerPayoutAmount.isPositive()) {
        payoutTx.addOutput(buyerPayoutAmount, Address.fromBase58(params, buyerAddressString));
    }
    if (sellerPayoutAmount.isPositive()) {
        payoutTx.addOutput(sellerPayoutAmount, Address.fromBase58(params, sellerAddressString));
    }

    // take care of sorting!
    Script redeemScript = get2of3MultiSigRedeemScript(buyerPubKey, sellerPubKey, arbitratorPubKey);
    Sha256Hash sigHash = payoutTx.hashForSignature(0, redeemScript, Transaction.SigHash.ALL, false);
    checkNotNull(tradersMultiSigKeyPair, "tradersMultiSigKeyPair must not be null");
    if (tradersMultiSigKeyPair.isEncrypted()) {
        checkNotNull(aesKey);
    }
    ECKey.ECDSASignature tradersSignature = tradersMultiSigKeyPair.sign(sigHash, aesKey).toCanonicalised();
    TransactionSignature tradersTxSig = new TransactionSignature(tradersSignature, Transaction.SigHash.ALL, false);
    TransactionSignature arbitratorTxSig = new TransactionSignature(ECKey.ECDSASignature.decodeFromDER(arbitratorSignature),
            Transaction.SigHash.ALL, false);
    // Take care of order of signatures. See comment below at getMultiSigRedeemScript (sort order needed here: arbitrator, seller, buyer)
    Script inputScript = ScriptBuilder.createP2SHMultiSigInputScript(ImmutableList.of(arbitratorTxSig, tradersTxSig),
            redeemScript);
    TransactionInput input = payoutTx.getInput(0);
    input.setScriptSig(inputScript);
    WalletService.printTx("disputed payoutTx", payoutTx);
    WalletService.verifyTransaction(payoutTx);
    WalletService.checkWalletConsistency(wallet);
    WalletService.checkScriptSig(payoutTx, input, 0);
    checkNotNull(input.getConnectedOutput(), "input.getConnectedOutput() must not be null");
    input.verify(input.getConnectedOutput());
    return payoutTx;
}
 
Example 20
Source File: TradeWalletService.java    From bisq with GNU Affero General Public License v3.0 4 votes vote down vote up
public void emergencySignAndPublishPayoutTxFrom2of2MultiSig(String depositTxHex,
                                                            Coin buyerPayoutAmount,
                                                            Coin sellerPayoutAmount,
                                                            Coin txFee,
                                                            String buyerAddressString,
                                                            String sellerAddressString,
                                                            String buyerPrivateKeyAsHex,
                                                            String sellerPrivateKeyAsHex,
                                                            String buyerPubKeyAsHex,
                                                            String sellerPubKeyAsHex,
                                                            TxBroadcaster.Callback callback)
        throws AddressFormatException, TransactionVerificationException, WalletException {
    byte[] buyerPubKey = ECKey.fromPublicOnly(Utils.HEX.decode(buyerPubKeyAsHex)).getPubKey();
    byte[] sellerPubKey = ECKey.fromPublicOnly(Utils.HEX.decode(sellerPubKeyAsHex)).getPubKey();

    Script p2SHMultiSigOutputScript = get2of2MultiSigOutputScript(buyerPubKey, sellerPubKey);

    Coin msOutput = buyerPayoutAmount.add(sellerPayoutAmount).add(txFee);
    TransactionOutput p2SHMultiSigOutput = new TransactionOutput(params, null, msOutput, p2SHMultiSigOutputScript.getProgram());
    Transaction depositTx = new Transaction(params);
    depositTx.addOutput(p2SHMultiSigOutput);

    Transaction payoutTx = new Transaction(params);
    Sha256Hash spendTxHash = Sha256Hash.wrap(depositTxHex);
    payoutTx.addInput(new TransactionInput(params, depositTx, p2SHMultiSigOutputScript.getProgram(), new TransactionOutPoint(params, 0, spendTxHash), msOutput));

    if (buyerPayoutAmount.isPositive()) {
        payoutTx.addOutput(buyerPayoutAmount, Address.fromBase58(params, buyerAddressString));
    }
    if (sellerPayoutAmount.isPositive()) {
        payoutTx.addOutput(sellerPayoutAmount, Address.fromBase58(params, sellerAddressString));
    }

    // take care of sorting!
    Script redeemScript = get2of2MultiSigRedeemScript(buyerPubKey, sellerPubKey);
    Sha256Hash sigHash = payoutTx.hashForSignature(0, redeemScript, Transaction.SigHash.ALL, false);

    ECKey buyerPrivateKey = ECKey.fromPrivate(Utils.HEX.decode(buyerPrivateKeyAsHex));
    checkNotNull(buyerPrivateKey, "key must not be null");
    ECKey.ECDSASignature buyerECDSASignature = buyerPrivateKey.sign(sigHash, aesKey).toCanonicalised();

    ECKey sellerPrivateKey = ECKey.fromPrivate(Utils.HEX.decode(sellerPrivateKeyAsHex));
    checkNotNull(sellerPrivateKey, "key must not be null");
    ECKey.ECDSASignature sellerECDSASignature = sellerPrivateKey.sign(sigHash, aesKey).toCanonicalised();

    TransactionSignature buyerTxSig = new TransactionSignature(buyerECDSASignature, Transaction.SigHash.ALL, false);
    TransactionSignature sellerTxSig = new TransactionSignature(sellerECDSASignature, Transaction.SigHash.ALL, false);
    Script inputScript = ScriptBuilder.createP2SHMultiSigInputScript(ImmutableList.of(sellerTxSig, buyerTxSig), redeemScript);

    TransactionInput input = payoutTx.getInput(0);
    input.setScriptSig(inputScript);
    WalletService.printTx("payoutTx", payoutTx);
    WalletService.verifyTransaction(payoutTx);
    WalletService.checkWalletConsistency(wallet);
    broadcastTx(payoutTx, callback, 20);
}