FixAdress entry persistence bug

This commit is contained in:
Manfred Karrer 2015-03-26 16:14:19 +01:00
parent ccd2e6b676
commit 2f911101ba
10 changed files with 69 additions and 38 deletions

View file

@ -23,6 +23,8 @@ import org.bitcoinj.crypto.DeterministicKey;
import java.io.Serializable;
import java.util.Arrays;
/**
* Is a minimalistic wallet abstraction used to separate transactions between different activities like:
* Registration, trade and arbiter deposit.
@ -31,9 +33,11 @@ public class AddressEntry implements Serializable {
// That object is saved to disc. We need to take care of changes to not break deserialization.
private static final long serialVersionUID = 1L;
// that will be restored from the wallet at deserialisation
private transient DeterministicKey keyPair;
private final String offerId;
private final Context context;
private transient DeterministicKey keyPair;
private final byte[] pubKey;
private final byte[] pubKeyHash;
private final NetworkParameters params;
@ -93,8 +97,11 @@ public class AddressEntry implements Serializable {
@Override
public String toString() {
return "AddressEntry{" +
"offerId='" + offerId +
", addressContext=" + context +
"offerId='" + offerId + '\'' +
", context=" + context +
", pubKey=" + Arrays.toString(pubKey) +
", pubKeyHash=" + Arrays.toString(pubKeyHash) +
", params=" + params +
'}';
}
}

View file

@ -46,13 +46,14 @@ public class AddressEntryList extends ArrayList<AddressEntry> implements Seriali
this.storage = storage;
}
public void init(Wallet wallet) {
public void onWalletReady(Wallet wallet) {
this.wallet = wallet;
AddressEntryList persisted = storage.initAndGetPersisted(this);
if (persisted != null) {
for (AddressEntry addressEntry : persisted) {
addressEntry.setDeterministicKey((DeterministicKey) wallet.findKeyFromPubHash(addressEntry.getPubKeyHash()));
this.add(addressEntry);
}
}
else {

View file

@ -37,8 +37,7 @@ public class BitcoinModule extends BitsquareModule {
@Override
protected void configure() {
bind(BitcoinNetwork.class).toInstance(
env.getProperty(BitcoinNetwork.KEY, BitcoinNetwork.class, BitcoinNetwork.DEFAULT));
bind(BitcoinNetwork.class).toInstance(env.getProperty(BitcoinNetwork.KEY, BitcoinNetwork.class, BitcoinNetwork.DEFAULT));
bind(FeePolicy.class).in(Singleton.class);
bindConstant().annotatedWith(named(UserAgent.NAME_KEY)).to(env.getRequiredProperty(UserAgent.NAME_KEY));
@ -47,10 +46,11 @@ public class BitcoinModule extends BitsquareModule {
File walletDir = new File(env.getRequiredProperty(WalletService.DIR_KEY));
bind(File.class).annotatedWith(named(WalletService.DIR_KEY)).toInstance(walletDir);
bindConstant().annotatedWith(named(WalletService.PREFIX_KEY)).to(
env.getRequiredProperty(WalletService.PREFIX_KEY));
bind(WalletService.class).in(Singleton.class);
bindConstant().annotatedWith(named(WalletService.PREFIX_KEY)).to(env.getRequiredProperty(WalletService.PREFIX_KEY));
bind(AddressEntryList.class).in(Singleton.class);
bind(TradeWalletService.class).in(Singleton.class);
bind(WalletService.class).in(Singleton.class);
bind(BlockChainService.class).in(Singleton.class);
}

View file

@ -48,6 +48,8 @@ import com.google.common.util.concurrent.ListenableFuture;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -81,17 +83,21 @@ public class TradeWalletService {
private static final Logger log = LoggerFactory.getLogger(TradeWalletService.class);
private final NetworkParameters params;
private final Wallet wallet;
private final WalletAppKit walletAppKit;
private Wallet wallet;
private WalletAppKit walletAppKit;
private final FeePolicy feePolicy;
public TradeWalletService(NetworkParameters params, Wallet wallet, WalletAppKit walletAppKit, FeePolicy feePolicy) {
this.params = params;
this.wallet = wallet;
this.walletAppKit = walletAppKit;
@Inject
public TradeWalletService(BitcoinNetwork bitcoinNetwork, FeePolicy feePolicy) {
this.params = bitcoinNetwork.getParameters();
this.feePolicy = feePolicy;
}
public void setWalletAppKit(WalletAppKit walletAppKit) {
this.walletAppKit = walletAppKit;
wallet = walletAppKit.wallet();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Trade fee
///////////////////////////////////////////////////////////////////////////////////////////
@ -142,12 +148,28 @@ public class TradeWalletService {
// Trade
///////////////////////////////////////////////////////////////////////////////////////////
private Coin getBalance(List<TransactionOutput> transactionOutputs, Address address) {
Coin balance = Coin.ZERO;
for (TransactionOutput transactionOutput : transactionOutputs) {
if (transactionOutput.getScriptPubKey().isSentToAddress() || transactionOutput.getScriptPubKey().isPayToScriptHash()) {
Address addressOutput = transactionOutput.getScriptPubKey().getToAddress(params);
if (addressOutput.equals(address))
balance = balance.add(transactionOutput.getValue());
}
}
return balance;
}
public Result createOffererDepositTxInputs(Coin offererInputAmount, AddressEntry offererAddressEntry) throws
TransactionVerificationException, WalletException {
log.trace("createOffererDepositTxInputs called");
log.trace("offererInputAmount " + offererInputAmount.toFriendlyString());
log.trace("offererAddressEntry " + offererAddressEntry.toString());
Coin balance = getBalance(wallet.calculateAllSpendCandidates(true), offererAddressEntry.getAddress());
log.trace("balance " + balance.toFriendlyString());
// We pay the tx fee 2 times to the deposit tx:
// 1. Will be spent when publishing the deposit tx (paid by offerer)
// 2. Will be added to the MS amount, so when publishing the payout tx the fee is already there and the outputs are not changed by fee reduction

View file

@ -87,6 +87,8 @@ public class WalletService {
private final Observable<Double> downloadProgress = downloadListener.getObservable();
private final WalletEventListener walletEventListener = new BitsquareWalletEventListener();
private final TradeWalletService tradeWalletService;
private final AddressEntryList addressEntryList;
private final NetworkParameters params;
private final FeePolicy feePolicy;
private final SignatureService signatureService;
@ -98,9 +100,7 @@ public class WalletService {
private Wallet wallet;
private AddressEntry registrationAddressEntry;
private AddressEntry arbitratorDepositAddressEntry;
private AddressEntryList addressEntryList;
private TradeWalletService tradeWalletService;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
@ -108,8 +108,9 @@ public class WalletService {
@Inject
public WalletService(BitcoinNetwork bitcoinNetwork, FeePolicy feePolicy, SignatureService signatureService,
AddressEntryList addressEntryList, UserAgent userAgent,
TradeWalletService tradeWalletService, AddressEntryList addressEntryList, UserAgent userAgent,
@Named(DIR_KEY) File walletDir, @Named(PREFIX_KEY) String walletPrefix) {
this.tradeWalletService = tradeWalletService;
this.addressEntryList = addressEntryList;
this.params = bitcoinNetwork.getParameters();
this.feePolicy = feePolicy;
@ -145,7 +146,8 @@ public class WalletService {
walletAppKit.peerGroup().setBloomFilterFalsePositiveRate(0.00001);
initWallet();
tradeWalletService = new TradeWalletService(params, wallet, walletAppKit, feePolicy);
// set after wallet is ready
tradeWalletService.setWalletAppKit(walletAppKit);
status.onCompleted();
}
@ -200,7 +202,7 @@ public class WalletService {
wallet = walletAppKit.wallet();
wallet.addEventListener(walletEventListener);
addressEntryList.init(wallet);
addressEntryList.onWalletReady(wallet);
registrationAddressEntry = addressEntryList.getRegistrationAddressEntry();
}

View file

@ -62,8 +62,9 @@ public class GuiModule extends BitsquareModule {
bind(ViewLoader.class).to(FxmlViewLoader.class).in(Singleton.class);
bind(CachingViewLoader.class).in(Singleton.class);
bind(OfferBook.class).in(Singleton.class);
bind(Navigation.class).in(Singleton.class);
bind(OfferBook.class).in(Singleton.class);
bind(OverlayManager.class).in(Singleton.class);
bind(BSFormatter.class).in(Singleton.class);

View file

@ -112,24 +112,18 @@ class PendingTradesDataModel implements Activatable, DataModel {
removeListenerFromSelectedTrade();
selectedItem = item;
isOfferer = getTrade().getOffer().getP2PSigPubKey().equals(user.getP2PSigPubKey());
if (selectedItem != null) {
isOfferer = getTrade().getOffer().getP2PSigPubKey().equals(user.getP2PSigPubKey());
Trade trade = getTrade();
if (trade instanceof TakerTrade)
takerProcessState.bind(((TakerTrade) trade).processStateProperty());
else
offererProcessState.bind(((OffererTrade) trade).processStateProperty());
Trade trade = getTrade();
if (trade instanceof TakerTrade)
takerProcessState.bind(((TakerTrade) trade).processStateProperty());
else
offererProcessState.bind(((OffererTrade) trade).processStateProperty());
log.trace("selectTrade trade.stateProperty().get() " + trade.processStateProperty().get());
log.trace("selectTrade trade.stateProperty().get() " + trade.processStateProperty().get());
if (trade.getDepositTx() != null)
txId.set(trade.getDepositTx().getHashAsString());
}
else {
txId.set(null);
}
if (trade.getDepositTx() != null)
txId.set(trade.getDepositTx().getHashAsString());
}
void fiatPaymentStarted() {

View file

@ -139,8 +139,10 @@ public class PendingTradesView extends ActivatableViewAndModel<AnchorPane, Pendi
model.withdrawAddressFocusOut(withdrawAddressTextField.getText());
};
selectedItemChangeListener = (ov, oldValue, newValue) -> {
model.selectTrade(newValue);
updateScreen();
if (newValue != null) {
model.selectTrade(newValue);
updateScreen();
}
};
withdrawAddressTextField.setValidator(model.getBtcAddressValidator());

View file

@ -53,6 +53,7 @@ public class PlaceOfferProtocol {
///////////////////////////////////////////////////////////////////////////////////////////
public void placeOffer() {
log.debug("model.offer.id" + model.offer.getId());
TaskRunner<PlaceOfferModel> taskRunner = new TaskRunner<>(model,
() -> {
log.debug("sequence at handleRequestTakeOfferMessage completed");

View file

@ -38,6 +38,7 @@ public class CreateOffererDepositTxInputs extends Task<OffererAsBuyerModel> {
@Override
protected void doRun() {
try {
log.debug("model.trade.id" + model.trade.getId());
Coin offererInputAmount = model.trade.getSecurityDeposit().add(FeePolicy.TX_FEE);
TradeWalletService.Result result = model.tradeWalletService.createOffererDepositTxInputs(offererInputAmount,
model.offerer.addressEntry);