update to bitcoinJ master

This commit is contained in:
Manfred Karrer 2014-08-05 23:30:17 +02:00
parent ff7aa52d39
commit e0e6df6383
14 changed files with 91 additions and 40 deletions

View file

@ -33,6 +33,8 @@ import javax.inject.Inject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import static com.google.bitcoin.script.ScriptOpCodes.OP_RETURN;
/** /**
* TODO: use walletextension (with protobuffer) instead of saving addressEntryList via storage * TODO: use walletextension (with protobuffer) instead of saving addressEntryList via storage
* TODO: use HD wallet features instead of addressEntryList * TODO: use HD wallet features instead of addressEntryList
@ -605,9 +607,8 @@ public class WalletFacade
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
//TODO priv key is null, use other signing key or find out why it is null at that moment byte[] data = cryptoFacade.getEmbeddedAccountRegistrationData(getRegistrationAddressInfo().getKey(), stringifiedBankAccounts);
//byte[] data = cryptoFacade.getEmbeddedAccountRegistrationData(getRegistrationAddressInfo().getKey(), stringifiedBankAccounts); tx.addOutput(Transaction.MIN_NONDUST_OUTPUT, new ScriptBuilder().op(OP_RETURN).data(data).build());
//tx.addOutput(Transaction.MIN_NONDUST_OUTPUT, new ScriptBuilder().op(OP_RETURN).data(data).build());
Coin fee = FeePolicy.ACCOUNT_REGISTRATION_FEE.subtract(Transaction.MIN_NONDUST_OUTPUT).subtract(FeePolicy.TX_FEE); Coin fee = FeePolicy.ACCOUNT_REGISTRATION_FEE.subtract(Transaction.MIN_NONDUST_OUTPUT).subtract(FeePolicy.TX_FEE);
log.trace("fee: " + fee.toFriendlyString()); log.trace("fee: " + fee.toFriendlyString());

View file

@ -1,12 +1,18 @@
package io.bitsquare.crypto; package io.bitsquare.crypto;
import com.google.bitcoin.core.ECKey; import com.google.bitcoin.core.ECKey;
import com.google.bitcoin.core.Sha256Hash;
import com.google.bitcoin.core.Utils; import com.google.bitcoin.core.Utils;
import com.google.bitcoin.crypto.KeyCrypterException;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
import java.nio.charset.Charset;
import java.security.SignatureException; import java.security.SignatureException;
import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.util.encoders.Base64;
/** /**
* That facade delivers crypto functionality from the bitcoinJ library * That facade delivers crypto functionality from the bitcoinJ library
@ -21,16 +27,42 @@ public class CryptoFacade
{ {
} }
// DeterministicKey does not support signMessage yet.
private String signMessage(ECKey key, String message, @Nullable KeyParameter aesKey) throws KeyCrypterException
{
byte[] data = Utils.formatMessageForSigning(message);
Sha256Hash hash = Sha256Hash.createDouble(data);
ECKey.ECDSASignature sig = key.sign(hash, aesKey);
// Now we have to work backwards to figure out the recId needed to recover the signature.
int recId = -1;
for (int i = 0; i < 4; i++)
{
ECKey k = ECKey.recoverFromSignature(i, sig, hash, key.isCompressed());
if (k != null && k.getPubKeyPoint().equals(key.getPubKeyPoint()))
{
recId = i;
break;
}
}
if (recId == -1)
throw new RuntimeException("Could not construct a recoverable key. This should never happen.");
int headerByte = recId + 27 + (key.isCompressed() ? 4 : 0);
byte[] sigData = new byte[65]; // 1 header + 32 bytes for R + 32 bytes for S
sigData[0] = (byte) headerByte;
System.arraycopy(Utils.bigIntegerToBytes(sig.r, 32), 0, sigData, 1, 32);
System.arraycopy(Utils.bigIntegerToBytes(sig.s, 32), 0, sigData, 33, 32);
return new String(Base64.encode(sigData), Charset.forName("UTF-8"));
}
public byte[] getEmbeddedAccountRegistrationData(ECKey registrationKey, String stringifiedBankAccounts) public byte[] getEmbeddedAccountRegistrationData(ECKey registrationKey, String stringifiedBankAccounts)
{ {
String signedBankAccountIDs = registrationKey.signMessage(stringifiedBankAccounts); String signedBankAccountIDs = signMessage(registrationKey, stringifiedBankAccounts, null);
return Utils.sha256hash160(concatenateChunks(stringifiedBankAccounts, signedBankAccountIDs).getBytes(Charsets.UTF_8)); return Utils.sha256hash160(concatenateChunks(stringifiedBankAccounts, signedBankAccountIDs).getBytes(Charsets.UTF_8));
} }
public String signContract(ECKey key, String contractAsJson) public String signContract(ECKey key, String contractAsJson)
{ {
return key.signMessage(contractAsJson); return signMessage(key, contractAsJson, null);
} }
// registration // registration
@ -38,7 +70,7 @@ public class CryptoFacade
{ {
try try
{ {
ECKey key = new ECKey(null, pubKey, true); ECKey key = ECKey.fromPublicOnly(pubKey);
key.verifyMessage(msg, sig); key.verifyMessage(msg, sig);
return true; return true;
} catch (SignatureException e) } catch (SignatureException e)

View file

@ -26,19 +26,19 @@
<Button onAction="#onClearLanguages" text="Clear" GridPane.columnIndex="2" GridPane.rowIndex="2"/> <Button onAction="#onClearLanguages" text="Clear" GridPane.columnIndex="2" GridPane.rowIndex="2"/>
<ComboBox fx:id="languageComboBox" onAction="#onAddLanguage" prefWidth="150.0" promptText="Add language" GridPane.columnIndex="3" GridPane.rowIndex="2"/> <ComboBox fx:id="languageComboBox" onAction="#onAddLanguage" prefWidth="150.0" promptText="Add language" GridPane.columnIndex="3" GridPane.rowIndex="2"/>
<Label text="Max. trade volume (BTC):" GridPane.rowIndex="3"/> <Label text="Max. trade volume:" GridPane.rowIndex="3"/>
<TextField fx:id="maxTradeVolumeTextField" promptText="Recommended: 0.1 - 2 BTC" GridPane.columnIndex="1" GridPane.rowIndex="3" GridPane.columnSpan="3"/> <TextField fx:id="maxTradeVolumeTextField" promptText="Recommended: 0.1 - 2 BTC" GridPane.columnIndex="1" GridPane.rowIndex="3" GridPane.columnSpan="3"/>
<Label text="Passive service fee (%):" GridPane.rowIndex="4"/> <Label text="Passive service fee (%):" GridPane.rowIndex="4"/>
<TextField fx:id="passiveServiceFeeTextField" promptText="Recommended: 0.1 - 1%" GridPane.columnIndex="1" GridPane.rowIndex="4" GridPane.columnSpan="3"/> <TextField fx:id="passiveServiceFeeTextField" promptText="Recommended: 0.1 - 1%" GridPane.columnIndex="1" GridPane.rowIndex="4" GridPane.columnSpan="3"/>
<Label text="Min. passive service fee (BTC)" GridPane.rowIndex="5"/> <Label text="Min. passive service fee" GridPane.rowIndex="5"/>
<TextField fx:id="minPassiveServiceFeeTextField" promptText="Recommended: 0.0001 - 0.005 BTC" GridPane.columnIndex="1" GridPane.rowIndex="5" GridPane.columnSpan="3"/> <TextField fx:id="minPassiveServiceFeeTextField" promptText="Recommended: 0.0001 - 0.005 BTC" GridPane.columnIndex="1" GridPane.rowIndex="5" GridPane.columnSpan="3"/>
<Label text="Arbitration fee (%):" GridPane.rowIndex="6"/> <Label text="Arbitration fee (%):" GridPane.rowIndex="6"/>
<TextField fx:id="arbitrationFeeTextField" promptText="Recommended: 5 - 20 %" GridPane.columnIndex="1" GridPane.rowIndex="6" GridPane.columnSpan="3"/> <TextField fx:id="arbitrationFeeTextField" promptText="Recommended: 5 - 20 %" GridPane.columnIndex="1" GridPane.rowIndex="6" GridPane.columnSpan="3"/>
<Label text="Min. arbitration fee (BTC):" GridPane.rowIndex="7"/> <Label text="Min. arbitration fee:" GridPane.rowIndex="7"/>
<TextField fx:id="minArbitrationFeeTextField" promptText="Recommended: 0.1 - 0.2 BTC" GridPane.columnIndex="1" GridPane.rowIndex="7" GridPane.columnSpan="3"/> <TextField fx:id="minArbitrationFeeTextField" promptText="Recommended: 0.1 - 0.2 BTC" GridPane.columnIndex="1" GridPane.rowIndex="7" GridPane.columnSpan="3"/>
<Label text="Method(s) used for arbitration:" GridPane.rowIndex="8"/> <Label text="Method(s) used for arbitration:" GridPane.rowIndex="8"/>

View file

@ -214,7 +214,7 @@ public class CreateOfferController implements Initializable, ChildController, Hi
if (user.getCurrentBankAccount() != null) if (user.getCurrentBankAccount() != null)
{ {
Coin amountAsCoin = BitSquareFormatter.parseBtcToCoin(getAmountString()); Coin amountAsCoin = BitSquareFormatter.parseBtcToCoin(getAmountString());
Coin minAmountAsCoin = BitSquareFormatter.parseBtcToCoin(getAmountString()); Coin minAmountAsCoin = BitSquareFormatter.parseBtcToCoin(getMinAmountString());
offer = new Offer(user.getMessagePublicKey(), offer = new Offer(user.getMessagePublicKey(),
direction, direction,
@ -354,6 +354,18 @@ public class CreateOfferController implements Initializable, ChildController, Hi
} }
} }
private String getMinAmountString()
{
try
{
BitSquareValidator.textFieldsHasPositiveDoubleValueWithReset(minAmountTextField);
return minAmountTextField.getText();
} catch (BitSquareValidator.ValidationException e)
{
return "0";
}
}
private double getCollateral() private double getCollateral()
{ {
// TODO // TODO

View file

@ -24,7 +24,7 @@
<Label text="EUR in total"/> <Label text="EUR in total"/>
</HBox> </HBox>
<Label text="Min. Amount:" GridPane.rowIndex="2"/> <Label text="Min. Amount (BTC):" GridPane.rowIndex="2"/>
<TextField fx:id="minAmountTextField" GridPane.columnIndex="1" GridPane.rowIndex="2"/> <TextField fx:id="minAmountTextField" GridPane.columnIndex="1" GridPane.rowIndex="2"/>
<Label fx:id="collateralLabel" text="Collateral:" GridPane.rowIndex="3"/> <Label fx:id="collateralLabel" text="Collateral:" GridPane.rowIndex="3"/>

View file

@ -20,7 +20,7 @@ public class OrderBookListItem
this.offer = offer; this.offer = offer;
this.price.set(BitSquareFormatter.formatPrice(offer.getPrice())); this.price.set(BitSquareFormatter.formatPrice(offer.getPrice()));
this.amount.set(BitSquareFormatter.formatCoinToBtc(offer.getAmount()) + " (" + BitSquareFormatter.formatCoinToBtc(offer.getMinAmount()) + ")"); this.amount.set(BitSquareFormatter.formatCoinToBtc(offer.getAmount()) + " (" + BitSquareFormatter.formatCoinToBtc(offer.getMinAmount()) + ")");
this.volume.set(BitSquareFormatter.formatVolumeWithMinVolume(offer.getVolume(), offer.getMinVolume())); this.volume.set(BitSquareFormatter.formatVolumeWithMinVolume(offer.getOfferVolume(), offer.getMinOfferVolume()));
} }

View file

@ -18,7 +18,7 @@
<Label text="Take offer:" id="form-header-text"/> <Label text="Take offer:" id="form-header-text"/>
<Label text="Amount (BTC):" GridPane.rowIndex="1"/> <Label text="Amount:" GridPane.rowIndex="1"/>
<ValidatedTextField fx:id="amountTextField" GridPane.rowIndex="1" GridPane.columnIndex="1"/> <ValidatedTextField fx:id="amountTextField" GridPane.rowIndex="1" GridPane.columnIndex="1"/>
<Label text="Price (EUR/BTC):" GridPane.rowIndex="2"/> <Label text="Price (EUR/BTC):" GridPane.rowIndex="2"/>
@ -122,7 +122,7 @@
<Label text="Trade completed" id="form-header-text"/> <Label text="Trade completed" id="form-header-text"/>
<Label text="You have sold (BTC):" GridPane.rowIndex="2"/> <Label text="You have sold:" GridPane.rowIndex="2"/>
<ValidatedTextField fx:id="summaryPaidTextField" GridPane.rowIndex="2" GridPane.columnIndex="1"/> <ValidatedTextField fx:id="summaryPaidTextField" GridPane.rowIndex="2" GridPane.columnIndex="1"/>
<Label text="You have received (EUR):" GridPane.rowIndex="3"/> <Label text="You have received (EUR):" GridPane.rowIndex="3"/>
@ -133,7 +133,7 @@
<Label text="Total fees (take offer fee + tx fee):" GridPane.rowIndex="5"/> <Label text="Total fees (take offer fee + tx fee):" GridPane.rowIndex="5"/>
<TextField fx:id="summaryFeesTextField" editable="false" GridPane.rowIndex="5" GridPane.columnIndex="1"/> <TextField fx:id="summaryFeesTextField" editable="false" GridPane.rowIndex="5" GridPane.columnIndex="1"/>
<Label text="Refunded collateral (BTC):" GridPane.rowIndex="6"/> <Label text="Refunded collateral:" GridPane.rowIndex="6"/>
<TextField fx:id="summaryCollateralTextField" editable="false" GridPane.rowIndex="6" GridPane.columnIndex="1"/> <TextField fx:id="summaryCollateralTextField" editable="false" GridPane.rowIndex="6" GridPane.columnIndex="1"/>
<Label text="Deposit transaction ID:" GridPane.rowIndex="7"/> <Label text="Deposit transaction ID:" GridPane.rowIndex="7"/>

View file

@ -200,8 +200,9 @@ public class TakerOfferController implements Initializable, ChildController
public void onPayoutTxPublished(Trade trade, String payoutTxId) public void onPayoutTxPublished(Trade trade, String payoutTxId)
{ {
accordion.setExpandedPane(summaryTitledPane); accordion.setExpandedPane(summaryTitledPane);
summaryPaidTextField.setText(BitSquareFormatter.formatCoinToBtcWithCode(trade.getTradeAmount())); summaryPaidTextField.setText(BitSquareFormatter.formatCoinToBtcWithCode(trade.getTradeAmount()));
summaryReceivedTextField.setText(BitSquareFormatter.formatVolume(trade.getOffer().getPrice() * trade.getTradeAmount().value)); summaryReceivedTextField.setText(BitSquareFormatter.formatVolume(trade.getTradeVolume()));
summaryFeesTextField.setText(BitSquareFormatter.formatCoinToBtcWithCode(FeePolicy.TAKE_OFFER_FEE.add(FeePolicy.TX_FEE))); summaryFeesTextField.setText(BitSquareFormatter.formatCoinToBtcWithCode(FeePolicy.TAKE_OFFER_FEE.add(FeePolicy.TX_FEE)));
summaryCollateralTextField.setText(BitSquareFormatter.formatCoinToBtcWithCode(trade.getCollateralAmount())); summaryCollateralTextField.setText(BitSquareFormatter.formatCoinToBtcWithCode(trade.getCollateralAmount()));
summaryDepositTxIdTextField.setText(depositTxId); summaryDepositTxIdTextField.setText(depositTxId);

View file

@ -23,7 +23,7 @@ public class OfferListItem
this.price.set(BitSquareFormatter.formatPrice(offer.getPrice())); this.price.set(BitSquareFormatter.formatPrice(offer.getPrice()));
this.amount.set(BitSquareFormatter.formatCoinToBtc(offer.getAmount()) + " (" + BitSquareFormatter.formatCoinToBtc(offer.getMinAmount()) + ")"); this.amount.set(BitSquareFormatter.formatCoinToBtc(offer.getAmount()) + " (" + BitSquareFormatter.formatCoinToBtc(offer.getMinAmount()) + ")");
this.volume.set(BitSquareFormatter.formatVolumeWithMinVolume(offer.getVolume(), offer.getMinVolume())); this.volume.set(BitSquareFormatter.formatVolumeWithMinVolume(offer.getOfferVolume(), offer.getMinOfferVolume()));
this.offerId = offer.getId(); this.offerId = offer.getId();
} }

View file

@ -292,16 +292,13 @@ public class PendingTradeController implements Initializable, ChildController, H
txTitleLabel.setText("Payout transaction ID:"); txTitleLabel.setText("Payout transaction ID:");
bankAccountDetailsHeaderLabel.setText("Summary"); bankAccountDetailsHeaderLabel.setText("Summary");
bankAccountTypeTitleLabel.setText("You have bought (BTC):"); bankAccountTypeTitleLabel.setText("You have bought:");
holderNameTitleLabel.setText("You have payed (" + trade.getOffer().getCurrency() + "):"); holderNameTitleLabel.setText("You have payed (" + trade.getOffer().getCurrency() + "):");
primaryBankAccountIDTitleLabel.setText("Total fees (offer fee + tx fee):"); primaryBankAccountIDTitleLabel.setText("Total fees (offer fee + tx fee):");
secondaryBankAccountIDTitleLabel.setText("Refunded collateral:"); secondaryBankAccountIDTitleLabel.setText("Refunded collateral:");
//TODO
String fiatPayed = BitSquareFormatter.formatVolume(trade.getOffer().getPrice() * trade.getTradeAmount().value);
bankAccountTypeTextField.setText(BitSquareFormatter.formatCoinToBtcWithCode(trade.getTradeAmount())); bankAccountTypeTextField.setText(BitSquareFormatter.formatCoinToBtcWithCode(trade.getTradeAmount()));
holderNameTextField.setText(fiatPayed); holderNameTextField.setText(BitSquareFormatter.formatVolume(trade.getTradeVolume()));
primaryBankAccountIDTextField.setText(BitSquareFormatter.formatCoinToBtcWithCode(FeePolicy.CREATE_OFFER_FEE.add(FeePolicy.TX_FEE))); primaryBankAccountIDTextField.setText(BitSquareFormatter.formatCoinToBtcWithCode(FeePolicy.CREATE_OFFER_FEE.add(FeePolicy.TX_FEE)));
secondaryBankAccountIDTextField.setText(BitSquareFormatter.formatCoinToBtcWithCode(trade.getCollateralAmount())); secondaryBankAccountIDTextField.setText(BitSquareFormatter.formatCoinToBtcWithCode(trade.getCollateralAmount()));

View file

@ -5,6 +5,7 @@ import io.bitsquare.bank.BankAccountType;
import io.bitsquare.locale.Country; import io.bitsquare.locale.Country;
import io.bitsquare.user.Arbitrator; import io.bitsquare.user.Arbitrator;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigDecimal;
import java.security.PublicKey; import java.security.PublicKey;
import java.util.*; import java.util.*;
@ -23,6 +24,7 @@ public class Offer implements Serializable
private final double price; private final double price;
private final Coin amount; private final Coin amount;
private final Coin minAmount; private final Coin minAmount;
//TODO use hex string
private final PublicKey messagePublicKey; private final PublicKey messagePublicKey;
private final BankAccountType bankAccountType; private final BankAccountType bankAccountType;
private final Country bankAccountCountry; private final Country bankAccountCountry;
@ -137,14 +139,21 @@ public class Offer implements Serializable
return acceptedLanguageLocales; return acceptedLanguageLocales;
} }
public double getVolume() public double getVolumeForCoin(Coin coin)
{ {
return price * amount.value; BigDecimal amountBD = BigDecimal.valueOf(coin.longValue());
BigDecimal volumeBD = amountBD.multiply(BigDecimal.valueOf(price));
return volumeBD.divide(BigDecimal.valueOf(Coin.COIN.value)).doubleValue();
} }
public double getMinVolume() public double getOfferVolume()
{ {
return price * minAmount.value; return getVolumeForCoin(amount);
}
public double getMinOfferVolume()
{
return getVolumeForCoin(minAmount);
} }
public String getOfferFeePaymentTxID() public String getOfferFeePaymentTxID()

View file

@ -38,6 +38,10 @@ public class Trade implements Serializable
_stateChangedProperty = new SimpleStringProperty(); _stateChangedProperty = new SimpleStringProperty();
} }
public double getTradeVolume()
{
return offer.getVolumeForCoin(tradeAmount);
}
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Setters // Setters

View file

@ -39,16 +39,13 @@ public class VerifyAndSignContract
// log.trace("Offerers contractAsJson: " + contractAsJson); // log.trace("Offerers contractAsJson: " + contractAsJson);
// log.trace("Takers contractAsJson: " + sharedModel.peersContractAsJson); // log.trace("Takers contractAsJson: " + sharedModel.peersContractAsJson);
//TODO not matching yet due refactoring... if (contractAsJson.equals(peersContractAsJson))
/* if (contractAsJson.equals(peersContractAsJson)) {
{ */ log.trace("The 2 contracts as json does match");
log.trace("The 2 contracts as json does match"); String signature = cryptoFacade.signContract(registrationKey, contractAsJson);
//String signature = cryptoFacade.signContract(registrationKey, contractAsJson); //log.trace("signature: " + signature);
String signature = "TODO"; resultHandler.onResult(contract, contractAsJson, signature);
//log.trace("signature: " + signature); }
resultHandler.onResult(contract, contractAsJson, signature);
/* }
else else
{ {
// TODO use diff output as feedback ? // TODO use diff output as feedback ?
@ -57,7 +54,7 @@ public class VerifyAndSignContract
log.error("Takers contractAsJson: " + peersContractAsJson); log.error("Takers contractAsJson: " + peersContractAsJson);
faultHandler.onFault(new Exception("Contracts are not matching")); faultHandler.onFault(new Exception("Contracts are not matching"));
} */ }
} }
public interface ResultHandler public interface ResultHandler

View file

@ -36,9 +36,7 @@ public class CreateAndSignContract
Contract contract = new Contract(offer, tradeAmount, takeOfferFeeTxId, peersAccountId, accountId, peersBankAccount, bankAccount, peersMessagePublicKey, messagePublicKey); Contract contract = new Contract(offer, tradeAmount, takeOfferFeeTxId, peersAccountId, accountId, peersBankAccount, bankAccount, peersMessagePublicKey, messagePublicKey);
String contractAsJson = Utilities.objectToJson(contract); String contractAsJson = Utilities.objectToJson(contract);
//TODO priv key is null, use other signing key or find out why it is null at that moment String signature = cryptoFacade.signContract(registrationKey, contractAsJson);
// String signature = cryptoFacade.signContract(registrationKey, contractAsJson);
String signature = "TODO priv key is null, use other signing key or find out why it is null at that moment";
resultHandler.onResult(contract, contractAsJson, signature); resultHandler.onResult(contract, contractAsJson, signature);
} catch (Throwable t) } catch (Throwable t)
{ {