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.LoggerFactory;
import static com.google.bitcoin.script.ScriptOpCodes.OP_RETURN;
/**
* TODO: use walletextension (with protobuffer) instead of saving addressEntryList via storage
* TODO: use HD wallet features instead of addressEntryList
@ -605,9 +607,8 @@ public class WalletFacade
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);
//tx.addOutput(Transaction.MIN_NONDUST_OUTPUT, new ScriptBuilder().op(OP_RETURN).data(data).build());
byte[] data = cryptoFacade.getEmbeddedAccountRegistrationData(getRegistrationAddressInfo().getKey(), stringifiedBankAccounts);
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);
log.trace("fee: " + fee.toFriendlyString());

View File

@ -1,12 +1,18 @@
package io.bitsquare.crypto;
import com.google.bitcoin.core.ECKey;
import com.google.bitcoin.core.Sha256Hash;
import com.google.bitcoin.core.Utils;
import com.google.bitcoin.crypto.KeyCrypterException;
import com.google.common.base.Charsets;
import java.nio.charset.Charset;
import java.security.SignatureException;
import javax.annotation.Nullable;
import javax.inject.Inject;
import org.slf4j.Logger;
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
@ -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)
{
String signedBankAccountIDs = registrationKey.signMessage(stringifiedBankAccounts);
String signedBankAccountIDs = signMessage(registrationKey, stringifiedBankAccounts, null);
return Utils.sha256hash160(concatenateChunks(stringifiedBankAccounts, signedBankAccountIDs).getBytes(Charsets.UTF_8));
}
public String signContract(ECKey key, String contractAsJson)
{
return key.signMessage(contractAsJson);
return signMessage(key, contractAsJson, null);
}
// registration
@ -38,7 +70,7 @@ public class CryptoFacade
{
try
{
ECKey key = new ECKey(null, pubKey, true);
ECKey key = ECKey.fromPublicOnly(pubKey);
key.verifyMessage(msg, sig);
return true;
} catch (SignatureException e)

View File

@ -26,19 +26,19 @@
<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"/>
<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"/>
<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"/>
<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"/>
<Label text="Arbitration fee (%):" GridPane.rowIndex="6"/>
<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"/>
<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)
{
Coin amountAsCoin = BitSquareFormatter.parseBtcToCoin(getAmountString());
Coin minAmountAsCoin = BitSquareFormatter.parseBtcToCoin(getAmountString());
Coin minAmountAsCoin = BitSquareFormatter.parseBtcToCoin(getMinAmountString());
offer = new Offer(user.getMessagePublicKey(),
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()
{
// TODO

View File

@ -24,7 +24,7 @@
<Label text="EUR in total"/>
</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"/>
<Label fx:id="collateralLabel" text="Collateral:" GridPane.rowIndex="3"/>

View File

@ -20,7 +20,7 @@ public class OrderBookListItem
this.offer = offer;
this.price.set(BitSquareFormatter.formatPrice(offer.getPrice()));
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="Amount (BTC):" GridPane.rowIndex="1"/>
<Label text="Amount:" GridPane.rowIndex="1"/>
<ValidatedTextField fx:id="amountTextField" GridPane.rowIndex="1" GridPane.columnIndex="1"/>
<Label text="Price (EUR/BTC):" GridPane.rowIndex="2"/>
@ -122,7 +122,7 @@
<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"/>
<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"/>
<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"/>
<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)
{
accordion.setExpandedPane(summaryTitledPane);
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)));
summaryCollateralTextField.setText(BitSquareFormatter.formatCoinToBtcWithCode(trade.getCollateralAmount()));
summaryDepositTxIdTextField.setText(depositTxId);

View File

@ -23,7 +23,7 @@ public class OfferListItem
this.price.set(BitSquareFormatter.formatPrice(offer.getPrice()));
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();
}

View File

@ -292,16 +292,13 @@ public class PendingTradeController implements Initializable, ChildController, H
txTitleLabel.setText("Payout transaction ID:");
bankAccountDetailsHeaderLabel.setText("Summary");
bankAccountTypeTitleLabel.setText("You have bought (BTC):");
bankAccountTypeTitleLabel.setText("You have bought:");
holderNameTitleLabel.setText("You have payed (" + trade.getOffer().getCurrency() + "):");
primaryBankAccountIDTitleLabel.setText("Total fees (offer fee + tx fee):");
secondaryBankAccountIDTitleLabel.setText("Refunded collateral:");
//TODO
String fiatPayed = BitSquareFormatter.formatVolume(trade.getOffer().getPrice() * trade.getTradeAmount().value);
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)));
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.user.Arbitrator;
import java.io.Serializable;
import java.math.BigDecimal;
import java.security.PublicKey;
import java.util.*;
@ -23,6 +24,7 @@ public class Offer implements Serializable
private final double price;
private final Coin amount;
private final Coin minAmount;
//TODO use hex string
private final PublicKey messagePublicKey;
private final BankAccountType bankAccountType;
private final Country bankAccountCountry;
@ -137,14 +139,21 @@ public class Offer implements Serializable
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()

View File

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

View File

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