mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-19 09:52:23 +01:00
payment process cleanup
This commit is contained in:
parent
a508f95582
commit
5d9d7a9a3d
@ -9,7 +9,7 @@ public class Fees
|
||||
{
|
||||
// min dust value lead to exception at for non standard to address pay scripts, so we use a value >= 7860 instead
|
||||
public static BigInteger MS_TX_FEE = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
|
||||
public static BigInteger ACCOUNT_REGISTRATION_FEE = Utils.toNanoCoins("0.01").subtract(Transaction.MIN_NONDUST_OUTPUT).subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE);
|
||||
public static BigInteger OFFER_CREATION_FEE = Utils.toNanoCoins("0.001").subtract(Transaction.MIN_NONDUST_OUTPUT).subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE);
|
||||
public static BigInteger ACCOUNT_REGISTRATION_FEE = Utils.toNanoCoins("0.01");
|
||||
public static BigInteger OFFER_CREATION_FEE = Utils.toNanoCoins("0.001");
|
||||
public static BigInteger OFFER_TAKER_FEE = OFFER_CREATION_FEE;
|
||||
}
|
||||
|
@ -28,12 +28,7 @@ import java.util.concurrent.ExecutionException;
|
||||
|
||||
import static com.google.bitcoin.script.ScriptOpCodes.OP_RETURN;
|
||||
|
||||
/**
|
||||
* That facade delivers wallet functionality from the bitcoinJ library
|
||||
* Code from BitcoinJ must not be used outside that facade.
|
||||
* That way a change of the library will only affect that class.
|
||||
*/
|
||||
public class WalletFacade implements WalletEventListener
|
||||
public class WalletFacade
|
||||
{
|
||||
public static final String MAIN_NET = "MAIN_NET";
|
||||
public static final String TEST_NET = "TEST_NET";
|
||||
@ -41,22 +36,13 @@ public class WalletFacade implements WalletEventListener
|
||||
|
||||
public static String WALLET_PREFIX = BitSquare.ID;
|
||||
|
||||
// for testing trade process between offerer and taker
|
||||
//public static String WALLET_PREFIX = "offerer"; // offerer
|
||||
//public static String WALLET_PREFIX = "taker"; // offerer
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(WalletFacade.class);
|
||||
|
||||
private NetworkParameters params;
|
||||
private WalletAppKit walletAppKit;
|
||||
private CryptoFacade cryptoFacade;
|
||||
|
||||
// that wallet is used only for the registration process
|
||||
//private AccountRegistrationWallet accountRegistrationWallet = null;
|
||||
|
||||
private List<DownloadListener> downloadListeners = new ArrayList<>();
|
||||
private List<WalletListener> walletListeners = new ArrayList<>();
|
||||
|
||||
|
||||
private Wallet wallet;
|
||||
private ECKey registrationKey;
|
||||
@ -115,30 +101,20 @@ public class WalletFacade implements WalletEventListener
|
||||
tradingKey = new ECKey();
|
||||
wallet.addKey(tradingKey);
|
||||
|
||||
log.info("getConnectedPeers " + walletAppKit.peerGroup().getConnectedPeers().size());
|
||||
wallet.allowSpendingUnconfirmedTransactions();
|
||||
// walletAppKit.peerGroup().setMaxConnections(10);
|
||||
//TODO for regtest set 1
|
||||
walletAppKit.peerGroup().setMinBroadcastConnections(1);
|
||||
|
||||
wallet.addEventListener(this);
|
||||
wallet.addWatchedAddress(tradingKey.toAddress(params));
|
||||
|
||||
// testTradeProcessDepositTx();
|
||||
// testTradeProcessPayOutTx();
|
||||
//wallet.addWatchedAddress(tradingKey.toAddress(params));
|
||||
}
|
||||
|
||||
public void shutDown()
|
||||
{
|
||||
/*if (accountRegistrationWallet != null)
|
||||
accountRegistrationWallet.shutDown(); */
|
||||
walletAppKit.stopAsync();
|
||||
walletAppKit.awaitTerminated();
|
||||
}
|
||||
|
||||
public void updateWallet()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Listener
|
||||
@ -154,26 +130,6 @@ public class WalletFacade implements WalletEventListener
|
||||
downloadListeners.remove(listener);
|
||||
}
|
||||
|
||||
/* public void addWalletListener(WalletListener listener)
|
||||
{
|
||||
walletListeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeWalletListener(WalletListener listener)
|
||||
{
|
||||
walletListeners.remove(listener);
|
||||
}
|
||||
|
||||
public void addRegistrationWalletListener(WalletListener listener)
|
||||
{
|
||||
getAccountRegistrationWallet().addWalletListener(listener);
|
||||
}
|
||||
|
||||
public void removeRegistrationWalletListener(WalletListener listener)
|
||||
{
|
||||
getAccountRegistrationWallet().removeWalletListener(listener);
|
||||
} */
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Trading wallet
|
||||
@ -184,25 +140,70 @@ public class WalletFacade implements WalletEventListener
|
||||
return wallet.getBalance(Wallet.BalanceType.ESTIMATED);
|
||||
}
|
||||
|
||||
public String getAddressAsString()
|
||||
public String getTradingAddress()
|
||||
{
|
||||
return tradingKey.toAddress(params).toString();
|
||||
}
|
||||
|
||||
public String payOfferFee(BigInteger fee, FutureCallback<Transaction> callback) throws InsufficientMoneyException
|
||||
public Wallet getWallet()
|
||||
{
|
||||
Transaction tx = new Transaction(params);
|
||||
//TransactionOutput output = new TransactionOutput(params, tx, Transaction.MIN_NONDUST_OUTPUT, WalletUtil.getEmptyOP_RETURNScript());
|
||||
tx.addOutput(Transaction.MIN_NONDUST_OUTPUT, WalletUtil.getEmptyOP_RETURNScript());
|
||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
|
||||
return wallet;
|
||||
}
|
||||
|
||||
public String getPubKeyAsHex()
|
||||
{
|
||||
return Utils.bytesToHexString(tradingKey.getPubKey());
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Account registration
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public Address getRegistrationAddress()
|
||||
{
|
||||
return registrationKey.toAddress(params);
|
||||
}
|
||||
|
||||
public ECKey getRegistrationKey()
|
||||
{
|
||||
return registrationKey;
|
||||
}
|
||||
|
||||
//TODO assume for now that there is only reg address funding, so total wallet balance = reg. balance
|
||||
public BigInteger getRegistrationBalance()
|
||||
{
|
||||
return wallet.getBalance(Wallet.BalanceType.ESTIMATED);
|
||||
}
|
||||
|
||||
public void publishRegistrationTxWithExtraData(String stringifiedBankAccounts) throws InsufficientMoneyException
|
||||
{
|
||||
byte[] dataToEmbed = cryptoFacade.getEmbeddedAccountRegistrationData(registrationKey, stringifiedBankAccounts);
|
||||
Script script = new ScriptBuilder().op(OP_RETURN).data(dataToEmbed).build();
|
||||
Transaction transaction = new Transaction(params);
|
||||
TransactionOutput dataOutput = new TransactionOutput(params, transaction, Transaction.MIN_NONDUST_OUTPUT, script.getProgram());
|
||||
transaction.addOutput(dataOutput);
|
||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(transaction);
|
||||
|
||||
// give fee to miners yet. Later it could be spent to other traders via lottery...
|
||||
sendRequest.fee = fee;
|
||||
|
||||
sendRequest.fee = Fees.ACCOUNT_REGISTRATION_FEE;
|
||||
Wallet.SendResult sendResult = wallet.sendCoins(sendRequest);
|
||||
Futures.addCallback(sendResult.broadcastComplete, callback);
|
||||
log.debug("Registration transaction: " + transaction.toString());
|
||||
//TODO
|
||||
Futures.addCallback(sendResult.broadcastComplete, new FutureCallback<Transaction>()
|
||||
{
|
||||
@Override
|
||||
public void onSuccess(Transaction result)
|
||||
{
|
||||
log.debug("sendResult onSuccess:" + result.toString());
|
||||
}
|
||||
|
||||
return tx.getHashAsString();
|
||||
@Override
|
||||
public void onFailure(Throwable t)
|
||||
{
|
||||
log.error("sendResult onFailure:" + t.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -210,6 +211,22 @@ public class WalletFacade implements WalletEventListener
|
||||
// Trade process
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public String payOfferFee(BigInteger fee, FutureCallback<Transaction> callback) throws InsufficientMoneyException
|
||||
{
|
||||
log.debug("payOfferFee fee=" + Utils.bitcoinValueToFriendlyString(fee));
|
||||
Transaction tx = new Transaction(params);
|
||||
tx.addOutput(Transaction.MIN_NONDUST_OUTPUT, WalletUtil.getEmptyOP_RETURNScript());
|
||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
|
||||
|
||||
sendRequest.fee = fee.subtract(Transaction.MIN_NONDUST_OUTPUT).subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE);
|
||||
|
||||
Wallet.SendResult sendResult = wallet.sendCoins(sendRequest);
|
||||
Futures.addCallback(sendResult.broadcastComplete, callback);
|
||||
|
||||
log.debug("tx=" + tx.toString());
|
||||
return tx.getHashAsString();
|
||||
}
|
||||
|
||||
public int getNumOfPeersSeenTx(String txID)
|
||||
{
|
||||
// TODO check from blockchain
|
||||
@ -217,344 +234,78 @@ public class WalletFacade implements WalletEventListener
|
||||
return 3;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Account registration
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
public Address getAccountRegistrationAddress()
|
||||
{
|
||||
return registrationKey.toAddress(params);
|
||||
}
|
||||
|
||||
/* public String getAccountRegistrationPubKey()
|
||||
{
|
||||
return Utils.bytesToHexString(getAccountRegistrationKey().getPubKey());
|
||||
} */
|
||||
|
||||
public BigInteger getAccountRegistrationBalance()
|
||||
{
|
||||
return wallet.getBalance(Wallet.BalanceType.ESTIMATED);
|
||||
// return getAccountRegistrationWallet().getBalance(Wallet.BalanceType.ESTIMATED);
|
||||
}
|
||||
|
||||
public void sendRegistrationTx(String stringifiedBankAccounts) throws InsufficientMoneyException
|
||||
{
|
||||
saveToBlockchain(cryptoFacade.getEmbeddedAccountRegistrationData(registrationKey, stringifiedBankAccounts));
|
||||
}
|
||||
|
||||
public ECKey getRegistrationKey()
|
||||
{
|
||||
return registrationKey;
|
||||
}
|
||||
|
||||
void saveToBlockchain(byte[] dataToEmbed) throws InsufficientMoneyException
|
||||
{
|
||||
Script script = new ScriptBuilder()
|
||||
.op(OP_RETURN)
|
||||
.data(dataToEmbed)
|
||||
.build();
|
||||
Transaction transaction = new Transaction(params);
|
||||
TransactionOutput dataOutput = new TransactionOutput(params,
|
||||
transaction,
|
||||
Transaction.MIN_NONDUST_OUTPUT,
|
||||
script.getProgram());
|
||||
transaction.addOutput(dataOutput);
|
||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(transaction);
|
||||
|
||||
// give fee to miners yet. Later it could be spent to other traders via lottery...
|
||||
sendRequest.fee = Fees.ACCOUNT_REGISTRATION_FEE;
|
||||
Wallet.SendResult sendResult = null;
|
||||
sendResult = wallet.sendCoins(sendRequest);
|
||||
log.info("Registration transaction: " + transaction.toString());
|
||||
//TODO
|
||||
Futures.addCallback(sendResult.broadcastComplete, new FutureCallback<Transaction>()
|
||||
{
|
||||
@Override
|
||||
public void onSuccess(Transaction result)
|
||||
{
|
||||
log.info("sendResult onSuccess:" + result.toString());
|
||||
// Platform.runLater(overlayUi::done);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t)
|
||||
{
|
||||
log.warn("sendResult onFailure:" + t.toString());
|
||||
// We died trying to empty the wallet.
|
||||
// crashAlert(t);
|
||||
}
|
||||
});
|
||||
|
||||
//TODO
|
||||
sendResult.tx.getConfidence().addEventListener((tx, reason) -> {
|
||||
//if (reason == TransactionConfidence.Listener.ChangeReason.SEEN_PEERS)
|
||||
//updateTitleForBroadcast();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getter
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*public int getRegConfNumBroadcastPeers()
|
||||
{
|
||||
return getAccountRegistrationWallet().getConfNumBroadcastPeers();
|
||||
}
|
||||
|
||||
public int getRegConfDepthInBlocks()
|
||||
{
|
||||
return WalletUtil.getConfDepthInBlocks(getAccountRegistrationWallet());
|
||||
} */
|
||||
|
||||
public Wallet getWallet()
|
||||
{
|
||||
return wallet;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Interface implementation: WalletEventListener
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
|
||||
{
|
||||
for (WalletListener walletListener : walletListeners)
|
||||
walletListener.onCoinsReceived(newBalance);
|
||||
|
||||
// log.info("onCoinsReceived");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx)
|
||||
{
|
||||
for (WalletListener walletListener : walletListeners)
|
||||
walletListener.onConfidenceChanged(tx.getConfidence().numBroadcastPeers(), WalletUtil.getConfDepthInBlocks(wallet));
|
||||
|
||||
// log.info("onTransactionConfidenceChanged " + tx.getConfidence().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCoinsSent(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
|
||||
{
|
||||
// log.info("onCoinsSent");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReorganize(Wallet wallet)
|
||||
{
|
||||
log.info("onReorganize");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWalletChanged(Wallet wallet)
|
||||
{
|
||||
// log.info("onWalletChanged");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeysAdded(Wallet wallet, List<ECKey> keys)
|
||||
{
|
||||
log.info("onKeysAdded");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScriptsAdded(Wallet wallet, List<Script> scripts)
|
||||
{
|
||||
log.info("onScriptsAdded");
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* public AccountRegistrationWallet getAccountRegistrationWallet()
|
||||
{
|
||||
if (accountRegistrationWallet == null)
|
||||
accountRegistrationWallet = new AccountRegistrationWallet(params, walletAppKit.chain(), walletAppKit.peerGroup());
|
||||
|
||||
return accountRegistrationWallet;
|
||||
}*/
|
||||
|
||||
private Script getMultiSigScript(String offererPubKey, String takerPubKey, String arbitratorPubKey)
|
||||
{
|
||||
ECKey offererKey = new ECKey(null, Utils.parseAsHexOrBase58(offererPubKey));
|
||||
ECKey takerKey = new ECKey(null, Utils.parseAsHexOrBase58(takerPubKey));
|
||||
ECKey arbitratorKey = new ECKey(null, Utils.parseAsHexOrBase58(arbitratorPubKey));
|
||||
|
||||
List<ECKey> keys = ImmutableList.of(offererKey, takerKey, arbitratorKey);
|
||||
return ScriptBuilder.createMultiSigOutputScript(2, keys);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// testTradeProcess methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// TODO only temp. for testing trade process between offerer and taker
|
||||
// deposit
|
||||
private void testTradeProcessDepositTx()
|
||||
{
|
||||
try
|
||||
{
|
||||
String tx1AsHex, tx2AsHex, tx2ScriptSigAsHex, tx2ConnOutAsHex;
|
||||
|
||||
BigInteger offererAmount = Utils.toNanoCoins("0.01");
|
||||
BigInteger takerAmount = Utils.toNanoCoins("0.02");
|
||||
|
||||
String takerPubKey = "0207cf5fb65d6923d5d41db21ceac9567a0fc3eb92c6137f274018381ced7b6568";
|
||||
String offererPubKey = "0352f2e34760514099f90b03aab91239466924c3b06047d3cf0e011f26ef96ceb7";
|
||||
String arbitratorPubKey = "";
|
||||
|
||||
// 1 offerer creates MS TX and pay in
|
||||
Transaction tx1 = offererCreatesMSTxAndAddPayment(offererAmount, offererPubKey, takerPubKey, arbitratorPubKey);
|
||||
tx1AsHex = Utils.bytesToHexString(tx1.bitcoinSerialize());
|
||||
|
||||
|
||||
tx1AsHex = "01000000014378dfcd19add18eb6f118a1e35ced127ff23c9dc5034eee1cda5b9caeb814f0000000006b4830450221008e599dd7bb7223c7b036869198b14f08009f9bc117709d23c249d0bdd6b483be022047be181f467782ea277b36890feb2f6de3ceddcedf8730a9f505bac36b3b015b01210352f2e34760514099f90b03aab91239466924c3b06047d3cf0e011f26ef96ceb7ffffffff0240420f00000000004852210352f2e34760514099f90b03aab91239466924c3b06047d3cf0e011f26ef96ceb7210207cf5fb65d6923d5d41db21ceac9567a0fc3eb92c6137f274018381ced7b65680053aeb077e605000000001976a9149fc3d8e0371b6eab89a8c3c015839f9e493ccf6588ac00000000";
|
||||
|
||||
// 2. taker pay in and sign
|
||||
/* Transaction tx2 = takerAddPaymentAndSign(takerAmount, msOutputAmount, offererPubKey, takerPubKey, arbitratorPubKey, tx1AsHex);
|
||||
tx2AsHex = Utils.bytesToHexString(tx2.bitcoinSerialize());
|
||||
tx2ScriptSigAsHex = Utils.bytesToHexString(tx2.getInput(1).getScriptBytes());
|
||||
tx2ConnOutAsHex = Utils.bytesToHexString(tx2.getInput(1).getConnectedOutput().getParentTransaction().bitcoinSerialize());
|
||||
*/
|
||||
|
||||
tx2AsHex = "01000000024378dfcd19add18eb6f118a1e35ced127ff23c9dc5034eee1cda5b9caeb814f0000000006b4830450221008e599dd7bb7223c7b036869198b14f08009f9bc117709d23c249d0bdd6b483be022047be181f467782ea277b36890feb2f6de3ceddcedf8730a9f505bac36b3b015b01210352f2e34760514099f90b03aab91239466924c3b06047d3cf0e011f26ef96ceb7ffffffffa58b22a93a0fcf99ba48aa3b96d842284b2b3d24f72d045cc192ea8a6b89435c010000006a47304402207f4beeb1a86432be0b4c3d4f4db7416b52b66c84383d1980d39e21d547a1762f02200405d0d4b80d1094e3a08cb39ef6f1161be163026d417af08d54c5a1cfdbbbeb01210207cf5fb65d6923d5d41db21ceac9567a0fc3eb92c6137f274018381ced7b6568ffffffff03c0c62d00000000004852210352f2e34760514099f90b03aab91239466924c3b06047d3cf0e011f26ef96ceb7210207cf5fb65d6923d5d41db21ceac9567a0fc3eb92c6137f274018381ced7b65680053aeb077e605000000001976a9149fc3d8e0371b6eab89a8c3c015839f9e493ccf6588ac7035d705000000001976a914e5175c1f71c28218306d4a27c8cec0269dddbbde88ac00000000";
|
||||
tx2ScriptSigAsHex = "47304402207f4beeb1a86432be0b4c3d4f4db7416b52b66c84383d1980d39e21d547a1762f02200405d0d4b80d1094e3a08cb39ef6f1161be163026d417af08d54c5a1cfdbbbeb01210207cf5fb65d6923d5d41db21ceac9567a0fc3eb92c6137f274018381ced7b6568";
|
||||
tx2ConnOutAsHex = "01000000014378dfcd19add18eb6f118a1e35ced127ff23c9dc5034eee1cda5b9caeb814f0010000006a473044022011431387fc19b093b26a6d2371995c828179aae68e94ad5804e5d0986a6b471302206abc2b698375620e65fc9970b7781da0af2179d1bdc4ebc82a13e285359a3ce7012103c7b9e9ef657705522c85b8429bb2b42c04f0fd4a09e0605cd7dd62ffecb57944ffffffff02c0ce823e000000001976a9142d1b4347ae850805f3badbb4b2949674f46c4ccd88ac00e1f505000000001976a914e5175c1f71c28218306d4a27c8cec0269dddbbde88ac00000000";
|
||||
|
||||
// 3. offerer sign and send
|
||||
Transaction tx3 = offererSignAndSendTx(tx1AsHex, tx2AsHex, tx2ConnOutAsHex, tx2ScriptSigAsHex, null);
|
||||
|
||||
log.info(tx3.toString()); // tx has 453 Bytes
|
||||
|
||||
} catch (AddressFormatException | InsufficientMoneyException | InterruptedException | ExecutionException e)
|
||||
{
|
||||
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
||||
} catch (Exception e)
|
||||
{
|
||||
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
|
||||
// payout
|
||||
private void testTradeProcessPayOutTx()
|
||||
{
|
||||
String depositTxAsHex, offererSignatureR, offererSignatureS;
|
||||
BigInteger offererPaybackAmount = Utils.toNanoCoins("0.029");
|
||||
BigInteger takerPaybackAmount = Utils.toNanoCoins("0.001");
|
||||
|
||||
ECKey takerKey = new ECKey(null, Utils.parseAsHexOrBase58("0207cf5fb65d6923d5d41db21ceac9567a0fc3eb92c6137f274018381ced7b6568"));
|
||||
String takerAddress = takerKey.toAddress(params).toString();
|
||||
|
||||
ECKey offererKey = new ECKey(null, Utils.parseAsHexOrBase58("0352f2e34760514099f90b03aab91239466924c3b06047d3cf0e011f26ef96ceb7"));
|
||||
String offererAddress = offererKey.toAddress(params).toString();
|
||||
|
||||
String depositTxID = "4142ee4877eb116abf955a7ec6ef2dc38133b793df762b76d75e3d7d4d8badc9";
|
||||
|
||||
try
|
||||
{
|
||||
// 1. offerer create and sign payout tx
|
||||
/* Pair<ECKey.ECDSASignature, Transaction> result = offererCreateAndSignPayoutTx(depositTxID,
|
||||
offererPaybackAmount,
|
||||
takerPaybackAmount,
|
||||
takerAddress);
|
||||
|
||||
ECKey.ECDSASignature offererSignature = result.getKey();
|
||||
Transaction depositTx = result.getValue();
|
||||
offererSignatureR = offererSignature.r.toString();
|
||||
offererSignatureS = offererSignature.s.toString();
|
||||
depositTxAsHex = Utils.bytesToHexString(depositTx.bitcoinSerialize()); */
|
||||
|
||||
|
||||
depositTxAsHex = "01000000024378dfcd19add18eb6f118a1e35ced127ff23c9dc5034eee1cda5b9caeb814f0000000006a473044022008addf33a37f8f058e629020d73c3873953e1eca559fcb59d9db651f2c9b524f02203cbfd319b2675974adfbff2cb605fc9b89a92f2f3197ee634b39c892fb57d1be01210352f2e34760514099f90b03aab91239466924c3b06047d3cf0e011f26ef96ceb7ffffffffa58b22a93a0fcf99ba48aa3b96d842284b2b3d24f72d045cc192ea8a6b89435c010000006a47304402207f4beeb1a86432be0b4c3d4f4db7416b52b66c84383d1980d39e21d547a1762f02200405d0d4b80d1094e3a08cb39ef6f1161be163026d417af08d54c5a1cfdbbbeb01210207cf5fb65d6923d5d41db21ceac9567a0fc3eb92c6137f274018381ced7b6568ffffffff03c0c62d00000000004852210352f2e34760514099f90b03aab91239466924c3b06047d3cf0e011f26ef96ceb7210207cf5fb65d6923d5d41db21ceac9567a0fc3eb92c6137f274018381ced7b65680053aeb077e605000000001976a9149fc3d8e0371b6eab89a8c3c015839f9e493ccf6588ac7035d705000000001976a914e5175c1f71c28218306d4a27c8cec0269dddbbde88ac00000000";
|
||||
offererSignatureR = "64562406184784382000330465585294975882418886289667123258365244289311131050102";
|
||||
offererSignatureS = "9282449224979858852843663340827968850695102089943078462704407873774672151491";
|
||||
|
||||
// 2. taker sign and publish tx
|
||||
Transaction takerTx = takerSignAndSendTx(depositTxAsHex,
|
||||
offererSignatureR,
|
||||
offererSignatureS,
|
||||
offererPaybackAmount,
|
||||
takerPaybackAmount,
|
||||
offererAddress, null);
|
||||
|
||||
log.info(takerTx.toString()); // tx has 265 Bytes
|
||||
|
||||
/*
|
||||
6606c366a487bff9e412d0b6c09c14916319932db5954bf5d8719f43f828a3ba: Unknown confidence level.
|
||||
in [] [30450221008ebd06e53ce1ab7b599098b3117f2073b1d224baae21190ef7839b70a638207602201485ae19965f2d954398f691aa40fecb4d08d625ae96037a4fc5eecb7a4803c301]
|
||||
[30440220521c485045a46fbb61c634ebf456c470f9c2f7307a743e3fce10b50f7a69115d0220249ff5f9796a9fcd12984afcfd3f7d16d2f8c49ddcef245db7c7b02b909af9a601]
|
||||
outpoint:4142ee4877eb116abf955a7ec6ef2dc38133b793df762b76d75e3d7d4d8badc9:0 hash160:[exception: Script not in the standard scriptPubKey form]
|
||||
out DUP HASH160 [9fc3d8e0371b6eab89a8c3c015839f9e493ccf65] EQUALVERIFY CHECKSIG 0.0289 BTC
|
||||
out DUP HASH160 [e5175c1f71c28218306d4a27c8cec0269dddbbde] EQUALVERIFY CHECKSIG 0.0009 BTC
|
||||
|
||||
2 [0352f2e34760514099f90b03aab91239466924c3b06047d3cf0e011f26ef96ceb7] [0207cf5fb65d6923d5d41db21ceac9567a0fc3eb92c6137f274018381ced7b6568] [] 3 CHECKMULTISIG
|
||||
*/
|
||||
|
||||
} catch (InsufficientMoneyException | AddressFormatException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String getMultiSigPubKeyAsHex()
|
||||
{
|
||||
return Utils.bytesToHexString(tradingKey.getPubKey());
|
||||
}
|
||||
|
||||
// deposit 1. offerer
|
||||
// Offerer creates deposit tx with his input and change output, the MS has just a dummy value at the moment
|
||||
public Transaction offererCreatesMSTxAndAddPayment(BigInteger offererInputAmount, String offererPubKey, String takerPubKey, String arbitratorPubKey) throws InsufficientMoneyException
|
||||
{
|
||||
log.debug("offererCreatesMSTxAndAddPayment");
|
||||
// use that to use the convenient api for getting the best coin selection and fee calculation
|
||||
// TODO should be constructed manually
|
||||
|
||||
// we pay the offererInputAmount to a dummy MS output, that way we get the best coin selection and fee calculation form the wallet and the correct change amount
|
||||
// we don't commit that tx to the wallet as it will be changed later and it's not signed yet
|
||||
// btc ntx fee will be included by the completeTx call, so we don't add it manually
|
||||
Transaction tx = new Transaction(params);
|
||||
Script multiSigOutputScript = getMultiSigScript(offererPubKey, takerPubKey, arbitratorPubKey);
|
||||
tx.addOutput(offererInputAmount, multiSigOutputScript);
|
||||
Wallet.SendRequest request = Wallet.SendRequest.forTx(tx);
|
||||
wallet.completeTx(request);
|
||||
|
||||
// TODO remove sig or use SigHash.NONE
|
||||
//tx.getInput(0).setScriptSig(null);
|
||||
// we remove the signature to make sure the tx is invalid to publish
|
||||
tx.getInput(0).setScriptSig(new Script(new byte[]{}));
|
||||
|
||||
// tx looks like:
|
||||
/*
|
||||
IN[0] offerer
|
||||
OUT[0] MS
|
||||
OUT[1] offerer change
|
||||
IN[0]
|
||||
OUT[0] MS offererInputAmount
|
||||
OUT[1] offerer change amount
|
||||
btc tx fee
|
||||
*/
|
||||
|
||||
log.debug("offererCreatesMSTxAndAddPayment tx = " + tx.toString());
|
||||
log.debug("tx = " + tx.toString());
|
||||
return tx;
|
||||
}
|
||||
|
||||
// deposit 2. taker
|
||||
// Taker put his input in, change the MS amount to the correct value and sign his input
|
||||
public Transaction takerAddPaymentAndSign(BigInteger takerAmount,
|
||||
BigInteger msOutputAmount,
|
||||
String offererPubKey,
|
||||
String takerPubKey,
|
||||
String arbitratorPubKey,
|
||||
String tx1AsHex
|
||||
String offerersPartialDepositTxAsHex
|
||||
) throws InsufficientMoneyException, ExecutionException, InterruptedException, AddressFormatException
|
||||
{
|
||||
log.debug("takerAddPaymentAndSign");
|
||||
Script multiSigOutputScript = getMultiSigScript(offererPubKey, takerPubKey, arbitratorPubKey);
|
||||
|
||||
// use that to use the convenient api for getting the best coin selection and fee calculation
|
||||
// TODO should be constructed manually
|
||||
// we pay the btc tx fee 2 times directly in the deposit tx:
|
||||
// 1. will be spent to miners when publishing the deposit tx (sum inputs - sum outputs = fee)
|
||||
// 2. will be as added to the MS amount, so when spending the payout tx the fee is already there
|
||||
// both traders pay 1 times a fee, so its equally split
|
||||
|
||||
// we construct a dummy tx to get the best coin selection and fee calculation form the wallet and the correct change amount
|
||||
// btc ntx fee will be included by the completeTx call, so we don't add it manually
|
||||
Transaction dummyTx = new Transaction(params);
|
||||
dummyTx.addOutput(takerAmount, multiSigOutputScript);
|
||||
wallet.completeTx(Wallet.SendRequest.forTx(dummyTx));
|
||||
wallet.completeTx(Wallet.SendRequest.forTx(dummyTx)); // it is signed but we don't care as it will not be used further
|
||||
|
||||
Transaction tx = new Transaction(params, Utils.parseAsHexOrBase58(tx1AsHex));
|
||||
// Now we construct the real MS tx from the passed tx from the offerer
|
||||
Transaction tx = new Transaction(params, Utils.parseAsHexOrBase58(offerersPartialDepositTxAsHex));
|
||||
|
||||
// it looks like that
|
||||
/*
|
||||
IN[0] offerer input
|
||||
OUT[0] MS offererInputAmount
|
||||
OUT[1] offerer change
|
||||
btc tx fee
|
||||
*/
|
||||
|
||||
// we add our inputs and outputs and change the MS amount to the correct one
|
||||
tx.addInput(dummyTx.getInput(0));
|
||||
tx.addOutput(dummyTx.getOutput(1));
|
||||
tx.getOutput(0).setValue(msOutputAmount);
|
||||
|
||||
log.debug("tx" + tx.toString());
|
||||
// we add the btc tx fee
|
||||
msOutputAmount = msOutputAmount.add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE);
|
||||
// and change the value of the MS output
|
||||
tx.getOutput(0).setValue(msOutputAmount);
|
||||
|
||||
TransactionInput input = tx.getInput(1);
|
||||
Script scriptPubKey = input.getConnectedOutput().getScriptPubKey();
|
||||
@ -569,18 +320,23 @@ public class WalletFacade implements WalletEventListener
|
||||
else
|
||||
throw new ScriptException("Don't know how to sign for this kind of scriptPubKey: " + scriptPubKey);
|
||||
|
||||
log.debug("correctlySpends?");
|
||||
log.debug("check if correctly spends");
|
||||
input.getScriptSig().correctlySpends(tx, 1, scriptPubKey, false);
|
||||
|
||||
log.debug("verify tx");
|
||||
tx.verify();
|
||||
|
||||
/*
|
||||
IN[0] offerer
|
||||
IN[1] taker signed
|
||||
OUT[0] MS
|
||||
IN[0] offerer 0.1001
|
||||
IN[1] taker signed 1.1001
|
||||
OUT[0] MS (include btc tx fee for payout tx) 1.2001
|
||||
OUT[1] offerer change
|
||||
OUT[2] taker change
|
||||
btc tx fee 0.0001
|
||||
*/
|
||||
|
||||
// wallet.commitTx(tx);
|
||||
wallet.commitTx(tx);
|
||||
log.debug("tx" + tx.toString());
|
||||
return tx;
|
||||
}
|
||||
|
||||
@ -751,43 +507,6 @@ public class WalletFacade implements WalletEventListener
|
||||
log.info("pre broadcastTransaction broadcastTransaction:" + wallet.getTransactions(true).size());
|
||||
ListenableFuture<Transaction> broadcastComplete = walletAppKit.peerGroup().broadcastTransaction(tx);
|
||||
|
||||
/* final TransactionBroadcast broadcast = new TransactionBroadcast(walletAppKit.peerGroup(), tx);
|
||||
broadcast.setMinConnections(1);
|
||||
Futures.addCallback(broadcast.future(), new FutureCallback<Transaction>() {
|
||||
@Override
|
||||
public void onSuccess(Transaction transaction) {
|
||||
// OK, now tell the wallet about the transaction. If the wallet created the transaction then
|
||||
// it already knows and will ignore this. If it's a transaction we received from
|
||||
// somebody else via a side channel and are now broadcasting, this will put it into the
|
||||
// wallet now we know it's valid.
|
||||
for (Wallet wallet : wallets) {
|
||||
// Assumption here is there are no dependencies of the created transaction.
|
||||
//
|
||||
// We may end up with two threads trying to do this in parallel - the wallet will
|
||||
// ignore whichever one loses the race.
|
||||
try {
|
||||
wallet.receivePending(transaction, null);
|
||||
} catch (VerificationException e) {
|
||||
throw new RuntimeException(e); // Cannot fail to verify a tx we created ourselves.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable throwable) {
|
||||
// This can't happen with the current code, but just in case one day that changes ...
|
||||
// runningBroadcasts.remove(broadcast);
|
||||
throw new RuntimeException(throwable);
|
||||
}
|
||||
}); */
|
||||
// Keep a reference to the TransactionBroadcast object. This is important because otherwise, the entire tree
|
||||
// of objects we just created would become garbage if the user doens't hold on to the returned future, and
|
||||
// eventually be collected. This in turn could result in the transaction not being committed to the wallet
|
||||
// at all.
|
||||
// runningBroadcasts.add(broadcast);
|
||||
// broadcast.broadcast();
|
||||
|
||||
|
||||
FutureCallback<Transaction> localCallback = new FutureCallback<Transaction>()
|
||||
{
|
||||
@Override
|
||||
@ -819,48 +538,130 @@ public class WalletFacade implements WalletEventListener
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private Script getMultiSigScript(String offererPubKey, String takerPubKey, String arbitratorPubKey)
|
||||
{
|
||||
ECKey offererKey = new ECKey(null, Utils.parseAsHexOrBase58(offererPubKey));
|
||||
ECKey takerKey = new ECKey(null, Utils.parseAsHexOrBase58(takerPubKey));
|
||||
ECKey arbitratorKey = new ECKey(null, Utils.parseAsHexOrBase58(arbitratorPubKey));
|
||||
|
||||
List<ECKey> keys = ImmutableList.of(offererKey, takerKey, arbitratorKey);
|
||||
return ScriptBuilder.createMultiSigOutputScript(2, keys);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
public ListenableFuture<Transaction> broadcastTransaction(final Transaction tx, final int minConnections) {
|
||||
final TransactionBroadcast broadcast = new TransactionBroadcast(walletAppKit.peerGroup(), tx);
|
||||
broadcast.setMinConnections(1);
|
||||
// Send the TX to the wallet once we have a successful broadcast.
|
||||
Futures.addCallback(broadcast.future(), new FutureCallback<Transaction>() {
|
||||
@Override
|
||||
public void onSuccess(Transaction transaction) {
|
||||
// OK, now tell the wallet about the transaction. If the wallet created the transaction then
|
||||
// it already knows and will ignore this. If it's a transaction we received from
|
||||
// somebody else via a side channel and are now broadcasting, this will put it into the
|
||||
// wallet now we know it's valid.
|
||||
for (Wallet wallet : wallets) {
|
||||
// Assumption here is there are no dependencies of the created transaction.
|
||||
//
|
||||
// We may end up with two threads trying to do this in parallel - the wallet will
|
||||
// ignore whichever one loses the race.
|
||||
try {
|
||||
wallet.receivePending(transaction, null);
|
||||
} catch (VerificationException e) {
|
||||
throw new RuntimeException(e); // Cannot fail to verify a tx we created ourselves.
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO only temp. for testing trade process between offerer and taker
|
||||
// deposit
|
||||
private void testTradeProcessDepositTx()
|
||||
{
|
||||
try
|
||||
{
|
||||
String tx1AsHex, tx2AsHex, tx2ScriptSigAsHex, tx2ConnOutAsHex;
|
||||
|
||||
BigInteger offererAmount = Utils.toNanoCoins("0.01");
|
||||
BigInteger takerAmount = Utils.toNanoCoins("0.02");
|
||||
|
||||
String takerPubKey = "0207cf5fb65d6923d5d41db21ceac9567a0fc3eb92c6137f274018381ced7b6568";
|
||||
String offererPubKey = "0352f2e34760514099f90b03aab91239466924c3b06047d3cf0e011f26ef96ceb7";
|
||||
String arbitratorPubKey = "";
|
||||
|
||||
// 1 offerer creates MS TX and pay in
|
||||
Transaction tx1 = offererCreatesMSTxAndAddPayment(offererAmount, offererPubKey, takerPubKey, arbitratorPubKey);
|
||||
tx1AsHex = Utils.bytesToHexString(tx1.bitcoinSerialize());
|
||||
|
||||
|
||||
tx1AsHex = "01000000014378dfcd19add18eb6f118a1e35ced127ff23c9dc5034eee1cda5b9caeb814f0000000006b4830450221008e599dd7bb7223c7b036869198b14f08009f9bc117709d23c249d0bdd6b483be022047be181f467782ea277b36890feb2f6de3ceddcedf8730a9f505bac36b3b015b01210352f2e34760514099f90b03aab91239466924c3b06047d3cf0e011f26ef96ceb7ffffffff0240420f00000000004852210352f2e34760514099f90b03aab91239466924c3b06047d3cf0e011f26ef96ceb7210207cf5fb65d6923d5d41db21ceac9567a0fc3eb92c6137f274018381ced7b65680053aeb077e605000000001976a9149fc3d8e0371b6eab89a8c3c015839f9e493ccf6588ac00000000";
|
||||
|
||||
// 2. taker pay in and sign
|
||||
/* Transaction tx2 = takerAddPaymentAndSign(takerAmount, msOutputAmount, offererPubKey, takerPubKey, arbitratorPubKey, tx1AsHex);
|
||||
tx2AsHex = Utils.bytesToHexString(tx2.bitcoinSerialize());
|
||||
tx2ScriptSigAsHex = Utils.bytesToHexString(tx2.getInput(1).getScriptBytes());
|
||||
tx2ConnOutAsHex = Utils.bytesToHexString(tx2.getInput(1).getConnectedOutput().getParentTransaction().bitcoinSerialize());
|
||||
*/
|
||||
|
||||
tx2AsHex = "01000000024378dfcd19add18eb6f118a1e35ced127ff23c9dc5034eee1cda5b9caeb814f0000000006b4830450221008e599dd7bb7223c7b036869198b14f08009f9bc117709d23c249d0bdd6b483be022047be181f467782ea277b36890feb2f6de3ceddcedf8730a9f505bac36b3b015b01210352f2e34760514099f90b03aab91239466924c3b06047d3cf0e011f26ef96ceb7ffffffffa58b22a93a0fcf99ba48aa3b96d842284b2b3d24f72d045cc192ea8a6b89435c010000006a47304402207f4beeb1a86432be0b4c3d4f4db7416b52b66c84383d1980d39e21d547a1762f02200405d0d4b80d1094e3a08cb39ef6f1161be163026d417af08d54c5a1cfdbbbeb01210207cf5fb65d6923d5d41db21ceac9567a0fc3eb92c6137f274018381ced7b6568ffffffff03c0c62d00000000004852210352f2e34760514099f90b03aab91239466924c3b06047d3cf0e011f26ef96ceb7210207cf5fb65d6923d5d41db21ceac9567a0fc3eb92c6137f274018381ced7b65680053aeb077e605000000001976a9149fc3d8e0371b6eab89a8c3c015839f9e493ccf6588ac7035d705000000001976a914e5175c1f71c28218306d4a27c8cec0269dddbbde88ac00000000";
|
||||
tx2ScriptSigAsHex = "47304402207f4beeb1a86432be0b4c3d4f4db7416b52b66c84383d1980d39e21d547a1762f02200405d0d4b80d1094e3a08cb39ef6f1161be163026d417af08d54c5a1cfdbbbeb01210207cf5fb65d6923d5d41db21ceac9567a0fc3eb92c6137f274018381ced7b6568";
|
||||
tx2ConnOutAsHex = "01000000014378dfcd19add18eb6f118a1e35ced127ff23c9dc5034eee1cda5b9caeb814f0010000006a473044022011431387fc19b093b26a6d2371995c828179aae68e94ad5804e5d0986a6b471302206abc2b698375620e65fc9970b7781da0af2179d1bdc4ebc82a13e285359a3ce7012103c7b9e9ef657705522c85b8429bb2b42c04f0fd4a09e0605cd7dd62ffecb57944ffffffff02c0ce823e000000001976a9142d1b4347ae850805f3badbb4b2949674f46c4ccd88ac00e1f505000000001976a914e5175c1f71c28218306d4a27c8cec0269dddbbde88ac00000000";
|
||||
|
||||
// 3. offerer sign and send
|
||||
Transaction tx3 = offererSignAndSendTx(tx1AsHex, tx2AsHex, tx2ConnOutAsHex, tx2ScriptSigAsHex, null);
|
||||
|
||||
log.info(tx3.toString()); // tx has 453 Bytes
|
||||
|
||||
} catch (AddressFormatException | InsufficientMoneyException | InterruptedException | ExecutionException e)
|
||||
{
|
||||
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
||||
} catch (Exception e)
|
||||
{
|
||||
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
|
||||
// payout
|
||||
private void testTradeProcessPayOutTx()
|
||||
{
|
||||
String depositTxAsHex, offererSignatureR, offererSignatureS;
|
||||
BigInteger offererPaybackAmount = Utils.toNanoCoins("0.029");
|
||||
BigInteger takerPaybackAmount = Utils.toNanoCoins("0.001");
|
||||
|
||||
ECKey takerKey = new ECKey(null, Utils.parseAsHexOrBase58("0207cf5fb65d6923d5d41db21ceac9567a0fc3eb92c6137f274018381ced7b6568"));
|
||||
String takerAddress = takerKey.toAddress(params).toString();
|
||||
|
||||
ECKey offererKey = new ECKey(null, Utils.parseAsHexOrBase58("0352f2e34760514099f90b03aab91239466924c3b06047d3cf0e011f26ef96ceb7"));
|
||||
String offererAddress = offererKey.toAddress(params).toString();
|
||||
|
||||
String depositTxID = "4142ee4877eb116abf955a7ec6ef2dc38133b793df762b76d75e3d7d4d8badc9";
|
||||
|
||||
try
|
||||
{
|
||||
// 1. offerer create and sign payout tx
|
||||
/* Pair<ECKey.ECDSASignature, Transaction> result = offererCreateAndSignPayoutTx(depositTxID,
|
||||
offererPaybackAmount,
|
||||
takerPaybackAmount,
|
||||
takerAddress);
|
||||
|
||||
ECKey.ECDSASignature offererSignature = result.getKey();
|
||||
Transaction depositTx = result.getValue();
|
||||
offererSignatureR = offererSignature.r.toString();
|
||||
offererSignatureS = offererSignature.s.toString();
|
||||
depositTxAsHex = Utils.bytesToHexString(depositTx.bitcoinSerialize()); */
|
||||
|
||||
|
||||
depositTxAsHex = "01000000024378dfcd19add18eb6f118a1e35ced127ff23c9dc5034eee1cda5b9caeb814f0000000006a473044022008addf33a37f8f058e629020d73c3873953e1eca559fcb59d9db651f2c9b524f02203cbfd319b2675974adfbff2cb605fc9b89a92f2f3197ee634b39c892fb57d1be01210352f2e34760514099f90b03aab91239466924c3b06047d3cf0e011f26ef96ceb7ffffffffa58b22a93a0fcf99ba48aa3b96d842284b2b3d24f72d045cc192ea8a6b89435c010000006a47304402207f4beeb1a86432be0b4c3d4f4db7416b52b66c84383d1980d39e21d547a1762f02200405d0d4b80d1094e3a08cb39ef6f1161be163026d417af08d54c5a1cfdbbbeb01210207cf5fb65d6923d5d41db21ceac9567a0fc3eb92c6137f274018381ced7b6568ffffffff03c0c62d00000000004852210352f2e34760514099f90b03aab91239466924c3b06047d3cf0e011f26ef96ceb7210207cf5fb65d6923d5d41db21ceac9567a0fc3eb92c6137f274018381ced7b65680053aeb077e605000000001976a9149fc3d8e0371b6eab89a8c3c015839f9e493ccf6588ac7035d705000000001976a914e5175c1f71c28218306d4a27c8cec0269dddbbde88ac00000000";
|
||||
offererSignatureR = "64562406184784382000330465585294975882418886289667123258365244289311131050102";
|
||||
offererSignatureS = "9282449224979858852843663340827968850695102089943078462704407873774672151491";
|
||||
|
||||
// 2. taker sign and publish tx
|
||||
Transaction takerTx = takerSignAndSendTx(depositTxAsHex,
|
||||
offererSignatureR,
|
||||
offererSignatureS,
|
||||
offererPaybackAmount,
|
||||
takerPaybackAmount,
|
||||
offererAddress, null);
|
||||
|
||||
log.info(takerTx.toString()); // tx has 265 Bytes
|
||||
|
||||
/*
|
||||
6606c366a487bff9e412d0b6c09c14916319932db5954bf5d8719f43f828a3ba: Unknown confidence level.
|
||||
in [] [30450221008ebd06e53ce1ab7b599098b3117f2073b1d224baae21190ef7839b70a638207602201485ae19965f2d954398f691aa40fecb4d08d625ae96037a4fc5eecb7a4803c301]
|
||||
[30440220521c485045a46fbb61c634ebf456c470f9c2f7307a743e3fce10b50f7a69115d0220249ff5f9796a9fcd12984afcfd3f7d16d2f8c49ddcef245db7c7b02b909af9a601]
|
||||
outpoint:4142ee4877eb116abf955a7ec6ef2dc38133b793df762b76d75e3d7d4d8badc9:0 hash160:[exception: Script not in the standard scriptPubKey form]
|
||||
out DUP HASH160 [9fc3d8e0371b6eab89a8c3c015839f9e493ccf65] EQUALVERIFY CHECKSIG 0.0289 BTC
|
||||
out DUP HASH160 [e5175c1f71c28218306d4a27c8cec0269dddbbde] EQUALVERIFY CHECKSIG 0.0009 BTC
|
||||
|
||||
2 [0352f2e34760514099f90b03aab91239466924c3b06047d3cf0e011f26ef96ceb7] [0207cf5fb65d6923d5d41db21ceac9567a0fc3eb92c6137f274018381ced7b6568] [] 3 CHECKMULTISIG
|
||||
*/
|
||||
|
||||
} catch (InsufficientMoneyException | AddressFormatException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable throwable) {
|
||||
// This can't happen with the current code, but just in case one day that changes ...
|
||||
runningBroadcasts.remove(broadcast);
|
||||
throw new RuntimeException(throwable);
|
||||
}
|
||||
});
|
||||
// Keep a reference to the TransactionBroadcast object. This is important because otherwise, the entire tree
|
||||
// of objects we just created would become garbage if the user doens't hold on to the returned future, and
|
||||
// eventually be collected. This in turn could result in the transaction not being committed to the wallet
|
||||
// at all.
|
||||
runningBroadcasts.add(broadcast);
|
||||
broadcast.broadcast();
|
||||
return broadcast.future();
|
||||
} */
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Inner classes
|
||||
|
@ -44,7 +44,7 @@ public class FundsController implements Initializable, ChildController
|
||||
@Override
|
||||
public void initialize(URL url, ResourceBundle rb)
|
||||
{
|
||||
String tradingAccountAddress = walletFacade.getAddressAsString();
|
||||
String tradingAccountAddress = walletFacade.getTradingAddress();
|
||||
tradingAccountTextField.setText(tradingAccountAddress);
|
||||
|
||||
copyIcon.setId("copy-icon");
|
||||
|
@ -163,8 +163,8 @@ public class SetupController implements Initializable, ChildController
|
||||
{
|
||||
try
|
||||
{
|
||||
walletFacade.sendRegistrationTx(user.getStringifiedBankAccounts());
|
||||
user.setAccountID(walletFacade.getAccountRegistrationAddress().toString());
|
||||
walletFacade.publishRegistrationTxWithExtraData(user.getStringifiedBankAccounts());
|
||||
user.setAccountID(walletFacade.getRegistrationAddress().toString());
|
||||
user.setMessagePubKeyAsHex(DSAKeyUtil.getHexStringFromPublicKey(messageFacade.getPubKey()));
|
||||
|
||||
storage.write(user.getClass().getName(), user);
|
||||
@ -201,7 +201,7 @@ public class SetupController implements Initializable, ChildController
|
||||
"Your trading account will be the source for your reputation in the trading platform.\n\n" +
|
||||
"You need at least 1 confirmation for doing the registration payment.");
|
||||
|
||||
String registrationAddress = walletFacade.getAccountRegistrationAddress().toString();
|
||||
String registrationAddress = walletFacade.getRegistrationAddress().toString();
|
||||
registrationAddressTextField.setText(registrationAddress);
|
||||
|
||||
copyIcon.setId("copy-icon");
|
||||
@ -215,8 +215,8 @@ public class SetupController implements Initializable, ChildController
|
||||
});
|
||||
|
||||
confidenceDisplay = new ConfidenceDisplay(walletFacade.getWallet(), confirmationLabel, balanceTextField, progressIndicator);
|
||||
paymentDoneButton.setDisable(walletFacade.getAccountRegistrationBalance().compareTo(BigInteger.ZERO) == 0);
|
||||
log.debug("getAccountRegistrationBalance " + walletFacade.getAccountRegistrationBalance().toString());
|
||||
paymentDoneButton.setDisable(walletFacade.getRegistrationBalance().compareTo(BigInteger.ZERO) == 0);
|
||||
log.debug("getAccountRegistrationBalance " + walletFacade.getRegistrationBalance().toString());
|
||||
walletFacade.getWallet().addEventListener(new WalletEventListener()
|
||||
{
|
||||
@Override
|
||||
@ -336,13 +336,13 @@ public class SetupController implements Initializable, ChildController
|
||||
accountSecondaryID.textProperty().addListener((ov, oldValue, newValue) -> checkCreateAccountButtonState());
|
||||
|
||||
//todo
|
||||
/* bankAccountTypesComboBox.getSelectionModel().select(0);
|
||||
bankAccountTypesComboBox.getSelectionModel().select(0);
|
||||
currencyComboBox.getSelectionModel().select(0);
|
||||
countryComboBox.getSelectionModel().select(0);
|
||||
accountTitle.setText("Sepa EUR Account");
|
||||
accountHolderName.setText("Alice");
|
||||
accountPrimaryID.setText("123456");
|
||||
accountSecondaryID.setText("7896541"); */
|
||||
accountSecondaryID.setText("7896541");
|
||||
}
|
||||
|
||||
private void setupSettingsScreen()
|
||||
|
@ -215,7 +215,7 @@ public class OffererPaymentProtocol
|
||||
log.debug("2.5 createDepositTx");
|
||||
|
||||
BigInteger offererInputAmount = trade.getTradeAmount().multiply(BigInteger.valueOf(offer.getCollateral())).divide(BigInteger.valueOf(100));
|
||||
String offererPubKey = walletFacade.getMultiSigPubKeyAsHex();
|
||||
String offererPubKey = walletFacade.getPubKeyAsHex();
|
||||
String takerPubKey = requestTradeMessage.getTakerMultiSigPubKey();
|
||||
String arbitratorPubKey = offer.getArbitrator().getPubKey();
|
||||
|
||||
@ -369,14 +369,6 @@ public class OffererPaymentProtocol
|
||||
else
|
||||
{
|
||||
log.error("3.3 verifyContract failed");
|
||||
//TODO ignore that for now... fee inconsistency...
|
||||
String signature = cryptoFacade.signContract(walletFacade.getRegistrationKey(), contractAsJson);
|
||||
trade.setContract(contract);
|
||||
trade.setContractAsJson(contractAsJson);
|
||||
trade.setContractTakerSignature(signature);
|
||||
log.debug("3.3 signature: " + signature);
|
||||
|
||||
signAndPublishDepositTx(requestTradeMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@ -570,7 +562,7 @@ public class OffererPaymentProtocol
|
||||
String offererSignatureS = offererSignature.s.toString();
|
||||
Transaction depositTx = result.getValue();
|
||||
String depositTxID = Utils.bytesToHexString(depositTx.bitcoinSerialize());
|
||||
String offererPayoutAddress = walletFacade.getAddressAsString();
|
||||
String offererPayoutAddress = walletFacade.getTradingAddress();
|
||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.BANK_TX_INITED, trade.getUid(),
|
||||
depositTxID,
|
||||
offererSignatureR,
|
||||
@ -613,7 +605,6 @@ public class OffererPaymentProtocol
|
||||
log.debug("3.14 onPayoutTxPublished");
|
||||
log.debug("3.14 TRADE COMPLETE!!!!!!!!!!!");
|
||||
|
||||
walletFacade.updateWallet();
|
||||
offererPaymentProtocolListener.onPayoutTxPublished(tradeMessage.getPayoutTxID());
|
||||
}
|
||||
|
||||
|
@ -264,7 +264,7 @@ public class TakerPaymentProtocol
|
||||
trade.getUid(),
|
||||
trade.getTradeAmount(),
|
||||
takeOfferFeeTxID,
|
||||
walletFacade.getMultiSigPubKeyAsHex());
|
||||
walletFacade.getPubKeyAsHex());
|
||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
||||
}
|
||||
|
||||
@ -364,12 +364,10 @@ public class TakerPaymentProtocol
|
||||
|
||||
BigInteger collateralAmount = trade.getTradeAmount().multiply(BigInteger.valueOf(offer.getCollateral())).divide(BigInteger.valueOf(100));
|
||||
BigInteger takerInputAmount = trade.getTradeAmount().add(collateralAmount);
|
||||
|
||||
// trade + 2 x coll + 1 x btc network fee
|
||||
BigInteger msOutputAmount = trade.getTradeAmount().add(collateralAmount).add(collateralAmount).add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE);
|
||||
BigInteger msOutputAmount = trade.getTradeAmount().add(collateralAmount).add(collateralAmount);
|
||||
|
||||
String offererPubKey = requestTradeMessage.getOffererPubKey();
|
||||
String takerPubKey = walletFacade.getMultiSigPubKeyAsHex();
|
||||
String takerPubKey = walletFacade.getPubKeyAsHex();
|
||||
String arbitratorPubKey = offer.getArbitrator().getPubKey();
|
||||
String preparedOffererDepositTxAsHex = requestTradeMessage.getPreparedOffererDepositTxAsHex();
|
||||
|
||||
@ -427,7 +425,7 @@ public class TakerPaymentProtocol
|
||||
|
||||
takerPaymentProtocolListener.onProgress(getProgress());
|
||||
|
||||
BankAccount bankAccount = user.getBankAccount(offer.getBankAccountUID());
|
||||
BankAccount bankAccount = user.getCurrentBankAccount();
|
||||
String accountID = user.getAccountID();
|
||||
String messagePubKey = user.getMessagePubKeyAsHex();
|
||||
String contractAsJson = trade.getContractAsJson();
|
||||
@ -437,7 +435,7 @@ public class TakerPaymentProtocol
|
||||
String txScriptSigAsHex = com.google.bitcoin.core.Utils.bytesToHexString(signedTakerDepositTx.getInput(1).getScriptBytes());
|
||||
String txConnOutAsHex = com.google.bitcoin.core.Utils.bytesToHexString(signedTakerDepositTx.getInput(1).getConnectedOutput().getParentTransaction().bitcoinSerialize());
|
||||
//TODO just 1 address supported yet
|
||||
String payoutAddress = walletFacade.getAddressAsString();
|
||||
String payoutAddress = walletFacade.getTradingAddress();
|
||||
log.debug("2.10 deposit txAsHex: " + signedTakerDepositTxAsHex);
|
||||
log.debug("2.10 txScriptSigAsHex: " + txScriptSigAsHex);
|
||||
log.debug("2.10 txConnOutAsHex: " + txConnOutAsHex);
|
||||
|
Loading…
Reference in New Issue
Block a user