Search in sources :

Example 1 with DeterministicKey

use of org.bitcoinj.crypto.DeterministicKey in project bitsquare by bitsquare.

the class AddressEntryList method onWalletReady.

public void onWalletReady(Wallet wallet) {
    this.wallet = wallet;
    AddressEntryList persisted = storage.initAndGetPersisted(this);
    if (persisted != null) {
        for (AddressEntry addressEntry : persisted) {
            DeterministicKey keyFromPubHash = (DeterministicKey) wallet.findKeyFromPubHash(addressEntry.getPubKeyHash());
            if (keyFromPubHash != null) {
                addressEntry.setDeterministicKey(keyFromPubHash);
                add(addressEntry);
            } else {
                log.warn("Key from addressEntry not found in that wallet " + addressEntry.toString());
            }
        }
    } else {
        add(new AddressEntry(wallet.freshReceiveKey(), wallet.getParams(), AddressEntry.Context.ARBITRATOR));
        storage.queueUpForSave();
    }
}
Also used : DeterministicKey(org.bitcoinj.crypto.DeterministicKey)

Example 2 with DeterministicKey

use of org.bitcoinj.crypto.DeterministicKey in project bisq-core by bisq-network.

the class DisputeManager method onDisputeResultMessage.

// We get that message at both peers. The dispute object is in context of the trader
private void onDisputeResultMessage(DisputeResultMessage disputeResultMessage) {
    DisputeResult disputeResult = disputeResultMessage.getDisputeResult();
    if (!isArbitrator(disputeResult)) {
        final String tradeId = disputeResult.getTradeId();
        Optional<Dispute> disputeOptional = findDispute(tradeId, disputeResult.getTraderId());
        final String uid = disputeResultMessage.getUid();
        if (disputeOptional.isPresent()) {
            cleanupRetryMap(uid);
            Dispute dispute = disputeOptional.get();
            DisputeCommunicationMessage disputeCommunicationMessage = disputeResult.getDisputeCommunicationMessage();
            if (!dispute.getDisputeCommunicationMessages().contains(disputeCommunicationMessage))
                dispute.addDisputeMessage(disputeCommunicationMessage);
            else
                log.warn("We got a dispute mail msg what we have already stored. TradeId = " + disputeCommunicationMessage.getTradeId());
            dispute.setIsClosed(true);
            if (dispute.disputeResultProperty().get() != null)
                log.warn("We got already a dispute result. That should only happen if a dispute needs to be closed " + "again because the first close did not succeed. TradeId = " + tradeId);
            dispute.setDisputeResult(disputeResult);
            // We need to avoid publishing the tx from both traders as it would create problems with zero confirmation withdrawals
            // There would be different transactions if both sign and publish (signers: once buyer+arb, once seller+arb)
            // The tx publisher is the winner or in case both get 50% the buyer, as the buyer has more inventive to publish the tx as he receives
            // more BTC as he has deposited
            final Contract contract = dispute.getContract();
            boolean isBuyer = keyRing.getPubKeyRing().equals(contract.getBuyerPubKeyRing());
            DisputeResult.Winner publisher = disputeResult.getWinner();
            // Default isLoserPublisher is set to false
            if (disputeResult.isLoserPublisher()) {
                // we invert the logic
                if (publisher == DisputeResult.Winner.BUYER)
                    publisher = DisputeResult.Winner.SELLER;
                else if (publisher == DisputeResult.Winner.SELLER)
                    publisher = DisputeResult.Winner.BUYER;
            }
            if ((isBuyer && publisher == DisputeResult.Winner.BUYER) || (!isBuyer && publisher == DisputeResult.Winner.SELLER)) {
                final Optional<Trade> tradeOptional = tradeManager.getTradeById(tradeId);
                Transaction payoutTx = null;
                if (tradeOptional.isPresent()) {
                    payoutTx = tradeOptional.get().getPayoutTx();
                } else {
                    final Optional<Tradable> tradableOptional = closedTradableManager.getTradableById(tradeId);
                    if (tradableOptional.isPresent() && tradableOptional.get() instanceof Trade) {
                        payoutTx = ((Trade) tradableOptional.get()).getPayoutTx();
                    }
                }
                if (payoutTx == null) {
                    if (dispute.getDepositTxSerialized() != null) {
                        try {
                            log.debug("do payout Transaction ");
                            byte[] multiSigPubKey = isBuyer ? contract.getBuyerMultiSigPubKey() : contract.getSellerMultiSigPubKey();
                            DeterministicKey multiSigKeyPair = walletService.getMultiSigKeyPair(dispute.getTradeId(), multiSigPubKey);
                            Transaction signedDisputedPayoutTx = tradeWalletService.traderSignAndFinalizeDisputedPayoutTx(dispute.getDepositTxSerialized(), disputeResult.getArbitratorSignature(), disputeResult.getBuyerPayoutAmount(), disputeResult.getSellerPayoutAmount(), contract.getBuyerPayoutAddressString(), contract.getSellerPayoutAddressString(), multiSigKeyPair, contract.getBuyerMultiSigPubKey(), contract.getSellerMultiSigPubKey(), disputeResult.getArbitratorPubKey());
                            Transaction committedDisputedPayoutTx = tradeWalletService.addTxToWallet(signedDisputedPayoutTx);
                            log.debug("broadcast committedDisputedPayoutTx");
                            tradeWalletService.broadcastTx(committedDisputedPayoutTx, new FutureCallback<Transaction>() {

                                @Override
                                public void onSuccess(Transaction transaction) {
                                    log.debug("BroadcastTx succeeded. Transaction:" + transaction);
                                    // after successful publish we send peer the tx
                                    dispute.setDisputePayoutTxId(transaction.getHashAsString());
                                    sendPeerPublishedPayoutTxMessage(transaction, dispute, contract);
                                    // set state after payout as we call swapTradeEntryToAvailableEntry
                                    if (tradeManager.getTradeById(dispute.getTradeId()).isPresent())
                                        tradeManager.closeDisputedTrade(dispute.getTradeId());
                                    else {
                                        Optional<OpenOffer> openOfferOptional = openOfferManager.getOpenOfferById(dispute.getTradeId());
                                        if (openOfferOptional.isPresent())
                                            openOfferManager.closeOpenOffer(openOfferOptional.get().getOffer());
                                    }
                                }

                                @Override
                                public void onFailure(@NotNull Throwable t) {
                                    log.error(t.getMessage());
                                }
                            }, 15);
                        } catch (AddressFormatException | WalletException | TransactionVerificationException e) {
                            e.printStackTrace();
                            log.error("Error at traderSignAndFinalizeDisputedPayoutTx " + e.getMessage());
                            throw new RuntimeException("Error at traderSignAndFinalizeDisputedPayoutTx " + e.toString());
                        }
                    } else {
                        log.warn("DepositTx is null. TradeId = " + tradeId);
                    }
                } else {
                    log.warn("We got already a payout tx. That might be the case if the other peer did not get the " + "payout tx and opened a dispute. TradeId = " + tradeId);
                    dispute.setDisputePayoutTxId(payoutTx.getHashAsString());
                    sendPeerPublishedPayoutTxMessage(payoutTx, dispute, contract);
                }
            } else {
                log.trace("We don't publish the tx as we are not the winning party.");
                // Clean up tangling trades
                if (dispute.disputeResultProperty().get() != null && dispute.isClosed() && tradeManager.getTradeById(dispute.getTradeId()).isPresent())
                    tradeManager.closeDisputedTrade(dispute.getTradeId());
            }
        } else {
            log.debug("We got a dispute result msg but we don't have a matching dispute. " + "That might happen when we get the disputeResultMessage before the dispute was created. " + "We try again after 2 sec. to apply the disputeResultMessage. TradeId = " + tradeId);
            if (!delayMsgMap.containsKey(uid)) {
                // We delay2 sec. to be sure the comm. msg gets added first
                Timer timer = UserThread.runAfter(() -> onDisputeResultMessage(disputeResultMessage), 2);
                delayMsgMap.put(uid, timer);
            } else {
                log.warn("We got a dispute result msg after we already repeated to apply the message after a delay. " + "That should never happen. TradeId = " + tradeId);
            }
        }
    } else {
        log.error("Arbitrator received disputeResultMessage. That must never happen.");
    }
}
Also used : Tradable(bisq.core.trade.Tradable) Trade(bisq.core.trade.Trade) DisputeCommunicationMessage(bisq.core.arbitration.messages.DisputeCommunicationMessage) WalletException(bisq.core.btc.exceptions.WalletException) AddressFormatException(org.bitcoinj.core.AddressFormatException) Optional(java.util.Optional) TransactionVerificationException(bisq.core.btc.exceptions.TransactionVerificationException) Transaction(org.bitcoinj.core.Transaction) Timer(bisq.common.Timer) Contract(bisq.core.trade.Contract) DeterministicKey(org.bitcoinj.crypto.DeterministicKey)

Example 3 with DeterministicKey

use of org.bitcoinj.crypto.DeterministicKey in project bisq-core by bisq-network.

the class GenericProposalService method prepareGenericProposal.

// TODO move code to consensus package
public GenericProposal prepareGenericProposal(GenericProposalPayload genericProposalPayload) throws InsufficientMoneyException, ChangeBelowDustException, TransactionVerificationException, WalletException {
    GenericProposal compensationRequest = new GenericProposal(genericProposalPayload);
    final Transaction preparedBurnFeeTx = bsqWalletService.getPreparedBurnFeeTx(ProposalConsensus.getCreateCompensationRequestFee(readableBsqBlockChain));
    checkArgument(!preparedBurnFeeTx.getInputs().isEmpty(), "preparedTx inputs must not be empty");
    // We use the key of the first BSQ input for signing the data
    TransactionOutput connectedOutput = preparedBurnFeeTx.getInputs().get(0).getConnectedOutput();
    checkNotNull(connectedOutput, "connectedOutput must not be null");
    DeterministicKey bsqKeyPair = bsqWalletService.findKeyFromPubKeyHash(connectedOutput.getScriptPubKey().getPubKeyHash());
    checkNotNull(bsqKeyPair, "bsqKeyPair must not be null");
    // We get the JSON of the object excluding signature and feeTxId
    String payloadAsJson = StringUtils.deleteWhitespace(Utilities.objectToJson(genericProposalPayload));
    // Signs a text message using the standard Bitcoin messaging signing format and returns the signature as a base64
    // encoded string.
    String signature = bsqKeyPair.signMessage(payloadAsJson);
    genericProposalPayload.setSignature(signature);
    String dataAndSig = payloadAsJson + signature;
    byte[] opReturnData = OpReturnData.getBytes(dataAndSig);
    final Transaction txWithBtcFee = btcWalletService.completePreparedGenericProposalTx(preparedBurnFeeTx, opReturnData);
    compensationRequest.setTx(bsqWalletService.signTx(txWithBtcFee));
    return compensationRequest;
}
Also used : TransactionOutput(org.bitcoinj.core.TransactionOutput) Transaction(org.bitcoinj.core.Transaction) DeterministicKey(org.bitcoinj.crypto.DeterministicKey)

Example 4 with DeterministicKey

use of org.bitcoinj.crypto.DeterministicKey in project bisq-core by bisq-network.

the class BtcWalletService method getMultiSigKeyPair.

public DeterministicKey getMultiSigKeyPair(String tradeId, byte[] pubKey) {
    Optional<AddressEntry> multiSigAddressEntryOptional = getAddressEntry(tradeId, AddressEntry.Context.MULTI_SIG);
    DeterministicKey multiSigKeyPair;
    if (multiSigAddressEntryOptional.isPresent()) {
        AddressEntry multiSigAddressEntry = multiSigAddressEntryOptional.get();
        multiSigKeyPair = multiSigAddressEntry.getKeyPair();
        if (!Arrays.equals(pubKey, multiSigAddressEntry.getPubKey())) {
            log.error("Pub Key from AddressEntry does not match key pair from trade data. Trade ID={}\n" + "We try to find the keypair in the wallet with the pubKey we found in the trade data.", tradeId);
            multiSigKeyPair = findKeyFromPubKey(pubKey);
        }
    } else {
        log.error("multiSigAddressEntry not found for trade ID={}.\n" + "We try to find the keypair in the wallet with the pubKey we found in the trade data.", tradeId);
        multiSigKeyPair = findKeyFromPubKey(pubKey);
    }
    return multiSigKeyPair;
}
Also used : AddressEntry(bisq.core.btc.AddressEntry) DeterministicKey(org.bitcoinj.crypto.DeterministicKey)

Example 5 with DeterministicKey

use of org.bitcoinj.crypto.DeterministicKey in project bisq-core by bisq-network.

the class AddressEntryList method onWalletReady.

// /////////////////////////////////////////////////////////////////////////////////////////
// API
// /////////////////////////////////////////////////////////////////////////////////////////
public void onWalletReady(Wallet wallet) {
    this.wallet = wallet;
    if (list != null) {
        list.forEach(addressEntry -> {
            DeterministicKey keyFromPubHash = (DeterministicKey) wallet.findKeyFromPubHash(addressEntry.getPubKeyHash());
            if (keyFromPubHash != null) {
                addressEntry.setDeterministicKey(keyFromPubHash);
            } else {
                log.error("Key from addressEntry not found in that wallet " + addressEntry.toString());
            }
        });
    } else {
        list = new ArrayList<>();
        add(new AddressEntry(wallet.freshReceiveKey(), AddressEntry.Context.ARBITRATOR));
        // In case we restore from seed words and have balance we need to add the relevant addresses to our list:
        if (wallet.getBalance().isPositive()) {
            wallet.getIssuedReceiveAddresses().forEach(address -> {
                log.info("Create AddressEntry for address={}", address);
                add(new AddressEntry((DeterministicKey) wallet.findKeyFromPubHash(address.getHash160()), AddressEntry.Context.AVAILABLE));
            });
        }
        persist();
    }
}
Also used : DeterministicKey(org.bitcoinj.crypto.DeterministicKey)

Aggregations

DeterministicKey (org.bitcoinj.crypto.DeterministicKey)19 Transaction (org.bitcoinj.core.Transaction)5 ByteBuffer (java.nio.ByteBuffer)3 Coin (org.bitcoinj.core.Coin)3 ChildNumber (org.bitcoinj.crypto.ChildNumber)3 AddressEntry (bisq.core.btc.AddressEntry)2 BtcWalletService (bisq.core.btc.wallet.BtcWalletService)2 TransactionOutput (org.bitcoinj.core.TransactionOutput)2 Timer (bisq.common.Timer)1 DisputeCommunicationMessage (bisq.core.arbitration.messages.DisputeCommunicationMessage)1 TransactionVerificationException (bisq.core.btc.exceptions.TransactionVerificationException)1 WalletException (bisq.core.btc.exceptions.WalletException)1 Offer (bisq.core.offer.Offer)1 Contract (bisq.core.trade.Contract)1 Tradable (bisq.core.trade.Tradable)1 Trade (bisq.core.trade.Trade)1 TradingPeer (bisq.core.trade.protocol.TradingPeer)1 ArrayList (java.util.ArrayList)1 Optional (java.util.Optional)1 AddressFormatException (org.bitcoinj.core.AddressFormatException)1