Use version byte and ripemd160 hash of json for comp. data. Use only primitive data in comp. data.

This commit is contained in:
Manfred Karrer 2016-12-21 23:05:04 +01:00
parent 5c9c14255c
commit 5dc00eb427
8 changed files with 259 additions and 187 deletions

View file

@ -80,4 +80,7 @@ public class Version {
", getP2PNetworkId()=" + getP2PMessageVersion() +
'}');
}
public static final byte COMP_REQUEST_VERSION = (byte) 0x01;
}

View file

@ -18,53 +18,50 @@
package io.bitsquare.dao.compensation;
import io.bitsquare.app.Version;
import io.bitsquare.common.util.JsonExclude;
import io.bitsquare.p2p.NodeAddress;
import io.bitsquare.p2p.storage.payload.LazyProcessedStoragePayload;
import io.bitsquare.p2p.storage.payload.PersistedStoragePayload;
import org.bitcoinj.core.Coin;
import org.bouncycastle.util.encoders.Hex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.security.PublicKey;
import java.util.Arrays;
import java.util.Date;
import java.util.concurrent.TimeUnit;
public final class CompensationRequestPayload implements LazyProcessedStoragePayload, PersistedStoragePayload {
// That object is sent over the wire, so we need to take care of version compatibility.
private static final long serialVersionUID = Version.P2P_NETWORK_VERSION;
private static final Logger log = LoggerFactory.getLogger(CompensationRequestPayload.class);
public static final long TTL = TimeUnit.DAYS.toMillis(30);
// public final String version;
public final byte version;
public final String uid;
public final String name;
public final String title;
public final String category;
public final String description;
public final String link;
public final Date startDate;
public final Date endDate;
public final Coin requestedBtc;
public final long startDate;
public final long endDate;
private final long requestedBtc;
public final String btcAddress;
public final NodeAddress nodeAddress;
public final Date creationDate;
//TODO store as byte array
public final PublicKey p2pStorageSignaturePubKey;
public final byte[] squPubKey;
// TODO optional TAC/VAT rules/refund...
private final String nodeAddress;
private final long creationDate;
@JsonExclude
private PublicKey p2pStorageSignaturePubKey;
// used for json
private final String p2pStorageSignaturePubKeyAsHex;
// Sha256Hash of CompensationRequest data including the signature but without feeTxId and hash
public byte[] hash;
// Signature of the JSON data of this object excluding the signature and feeTxId fields using the standard Bitcoin
// messaging signing format as a base64 encoded string.
@JsonExclude
public String signature;
// Signature of CompensationRequest data without signature, hash and feeTxId
public byte[] signature;
public byte[] OP_RETURN_hash;
// Set after we signed and set the hash. The hash is used in the OP_RETURN of the fee tx
@JsonExclude
public String feeTxId;
public CompensationRequestPayload(String uid,
@ -78,23 +75,33 @@ public final class CompensationRequestPayload implements LazyProcessedStoragePay
Coin requestedBtc,
String btcAddress,
NodeAddress nodeAddress,
PublicKey p2pStorageSignaturePubKey,
byte[] squPubKey) {
PublicKey p2pStorageSignaturePubKey) {
version = Version.COMP_REQUEST_VERSION;
creationDate = new Date().getTime();
creationDate = new Date();
this.uid = uid;
this.name = name;
this.title = title;
this.category = category;
this.description = description;
this.link = link;
this.startDate = startDate;
this.endDate = endDate;
this.requestedBtc = requestedBtc;
this.startDate = startDate.getTime();
this.endDate = endDate.getTime();
this.requestedBtc = requestedBtc.value;
this.btcAddress = btcAddress;
this.nodeAddress = nodeAddress;
this.nodeAddress = nodeAddress.getFullAddress();
this.p2pStorageSignaturePubKey = p2pStorageSignaturePubKey;
this.squPubKey = squPubKey;
p2pStorageSignaturePubKeyAsHex = Hex.toHexString(p2pStorageSignaturePubKey.getEncoded());
}
public void setSignature(String signature) {
this.signature = signature;
}
// Called after tx is published
public void setFeeTxId(String feeTxId) {
this.feeTxId = feeTxId;
}
@Override
@ -107,18 +114,24 @@ public final class CompensationRequestPayload implements LazyProcessedStoragePay
return p2pStorageSignaturePubKey;
}
public void setSignature(byte[] signature) {
this.signature = signature;
public Date getStartDate() {
return new Date(startDate);
}
public void setHash(byte[] hash) {
this.hash = hash;
public Date getEndDate() {
return new Date(endDate);
}
// Called after tx is published
public void setFeeTxId(String feeTxId) {
this.feeTxId = feeTxId;
public Date getCreationDate() {
return new Date(creationDate);
}
public Coin getRequestedBtc() {
return Coin.valueOf(requestedBtc);
}
public NodeAddress getNodeAddress() {
return new NodeAddress(nodeAddress);
}
public String getShortId() {
@ -130,71 +143,71 @@ public final class CompensationRequestPayload implements LazyProcessedStoragePay
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CompensationRequestPayload comPreqPayload = (CompensationRequestPayload) o;
CompensationRequestPayload that = (CompensationRequestPayload) o;
if (uid != null ? !uid.equals(comPreqPayload.uid) : comPreqPayload.uid != null) return false;
if (name != null ? !name.equals(comPreqPayload.name) : comPreqPayload.name != null) return false;
if (title != null ? !title.equals(comPreqPayload.title) : comPreqPayload.title != null) return false;
if (category != null ? !category.equals(comPreqPayload.category) : comPreqPayload.category != null)
if (version != that.version) return false;
if (startDate != that.startDate) return false;
if (endDate != that.endDate) return false;
if (requestedBtc != that.requestedBtc) return false;
if (creationDate != that.creationDate) return false;
if (uid != null ? !uid.equals(that.uid) : that.uid != null) return false;
if (name != null ? !name.equals(that.name) : that.name != null) return false;
if (title != null ? !title.equals(that.title) : that.title != null) return false;
if (category != null ? !category.equals(that.category) : that.category != null) return false;
if (description != null ? !description.equals(that.description) : that.description != null) return false;
if (link != null ? !link.equals(that.link) : that.link != null) return false;
if (btcAddress != null ? !btcAddress.equals(that.btcAddress) : that.btcAddress != null) return false;
if (nodeAddress != null ? !nodeAddress.equals(that.nodeAddress) : that.nodeAddress != null) return false;
if (p2pStorageSignaturePubKey != null ? !p2pStorageSignaturePubKey.equals(that.p2pStorageSignaturePubKey) : that.p2pStorageSignaturePubKey != null)
return false;
if (description != null ? !description.equals(comPreqPayload.description) : comPreqPayload.description != null)
if (p2pStorageSignaturePubKeyAsHex != null ? !p2pStorageSignaturePubKeyAsHex.equals(that.p2pStorageSignaturePubKeyAsHex) : that.p2pStorageSignaturePubKeyAsHex != null)
return false;
if (link != null ? !link.equals(comPreqPayload.link) : comPreqPayload.link != null) return false;
if (startDate != null ? !startDate.equals(comPreqPayload.startDate) : comPreqPayload.startDate != null)
return false;
if (endDate != null ? !endDate.equals(comPreqPayload.endDate) : comPreqPayload.endDate != null) return false;
if (requestedBtc != null ? !requestedBtc.equals(comPreqPayload.requestedBtc) : comPreqPayload.requestedBtc != null)
return false;
if (btcAddress != null ? !btcAddress.equals(comPreqPayload.btcAddress) : comPreqPayload.btcAddress != null)
return false;
if (nodeAddress != null ? !nodeAddress.equals(comPreqPayload.nodeAddress) : comPreqPayload.nodeAddress != null)
return false;
if (creationDate != null ? !creationDate.equals(comPreqPayload.creationDate) : comPreqPayload.creationDate != null)
return false;
if (p2pStorageSignaturePubKey != null ? !p2pStorageSignaturePubKey.equals(comPreqPayload.p2pStorageSignaturePubKey) : comPreqPayload.p2pStorageSignaturePubKey != null)
return false;
return Arrays.equals(squPubKey, comPreqPayload.squPubKey);
if (signature != null ? !signature.equals(that.signature) : that.signature != null) return false;
return !(feeTxId != null ? !feeTxId.equals(that.feeTxId) : that.feeTxId != null);
}
@Override
public int hashCode() {
int result = uid != null ? uid.hashCode() : 0;
int result = (int) version;
result = 31 * result + (uid != null ? uid.hashCode() : 0);
result = 31 * result + (name != null ? name.hashCode() : 0);
result = 31 * result + (title != null ? title.hashCode() : 0);
result = 31 * result + (category != null ? category.hashCode() : 0);
result = 31 * result + (description != null ? description.hashCode() : 0);
result = 31 * result + (link != null ? link.hashCode() : 0);
result = 31 * result + (startDate != null ? startDate.hashCode() : 0);
result = 31 * result + (endDate != null ? endDate.hashCode() : 0);
result = 31 * result + (requestedBtc != null ? requestedBtc.hashCode() : 0);
result = 31 * result + (int) (startDate ^ (startDate >>> 32));
result = 31 * result + (int) (endDate ^ (endDate >>> 32));
result = 31 * result + (int) (requestedBtc ^ (requestedBtc >>> 32));
result = 31 * result + (btcAddress != null ? btcAddress.hashCode() : 0);
result = 31 * result + (nodeAddress != null ? nodeAddress.hashCode() : 0);
result = 31 * result + (creationDate != null ? creationDate.hashCode() : 0);
result = 31 * result + (int) (creationDate ^ (creationDate >>> 32));
result = 31 * result + (p2pStorageSignaturePubKey != null ? p2pStorageSignaturePubKey.hashCode() : 0);
result = 31 * result + (squPubKey != null ? Arrays.hashCode(squPubKey) : 0);
result = 31 * result + (p2pStorageSignaturePubKeyAsHex != null ? p2pStorageSignaturePubKeyAsHex.hashCode() : 0);
result = 31 * result + (signature != null ? signature.hashCode() : 0);
result = 31 * result + (feeTxId != null ? feeTxId.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "CompensationRequestPayload{" +
"uid='" + uid + '\'' +
", text='" + name + '\'' +
"version=" + version +
", uid='" + uid + '\'' +
", name='" + name + '\'' +
", title='" + title + '\'' +
", category='" + category + '\'' +
", description='" + description + '\'' +
", link='" + link + '\'' +
", startDate=" + startDate +
", endDate=" + endDate +
", startDate=" + getStartDate() +
", endDate=" + getEndDate() +
", requestedBtc=" + requestedBtc +
", btcAddress='" + btcAddress + '\'' +
", nodeAddress=" + nodeAddress +
", pubKey=" + Arrays.toString(squPubKey) +
", signature=" + signature +
", hash=" + hash +
", feeTxId=" + feeTxId +
", nodeAddress='" + getNodeAddress() + '\'' +
", creationDate=" + getCreationDate() +
", p2pStorageSignaturePubKeyAsHex='" + p2pStorageSignaturePubKeyAsHex + '\'' +
", signature='" + signature + '\'' +
", feeTxId='" + feeTxId + '\'' +
'}';
}
}

View file

@ -29,6 +29,7 @@ public final class VoteItemCollection extends ArrayList<VoteItem> implements Per
private static final long serialVersionUID = Version.LOCAL_DB_VERSION;
private static final Logger log = LoggerFactory.getLogger(VoteItemCollection.class);
private boolean isMyVote;
public VoteItemCollection() {
add(new VoteItem(VotingCodes.Code.CREATE_OFFER_FEE, "Create offer fee", (byte) 0));
@ -36,4 +37,12 @@ public final class VoteItemCollection extends ArrayList<VoteItem> implements Per
add(new VoteItem(VotingCodes.Code.PERIOD_UNTIL_NEXT_VOTING, "Period until next voting", (byte) 0));
add(new CompensationRequestVoteItemCollection(VotingCodes.Code.COMP_REQUEST_MAPS, "CompensationRequest"));
}
public void setIsMyVote(boolean isMyVote) {
this.isMyVote = isMyVote;
}
public boolean isMyVote() {
return isMyVote;
}
}

View file

@ -37,18 +37,18 @@ public class VoteManager {
private final BtcWalletService btcWalletService;
private final SquWalletService squWalletService;
private FeeService feeService;
private final Storage<ArrayList<VoteItemCollection>> voteItemCollectionStorage;
private final Storage<ArrayList<VoteItemCollection>> voteItemCollectionsStorage;
private ArrayList<VoteItemCollection> voteItemCollections = new ArrayList<>();
private VoteItemCollection currentVoteItemCollection;
@Inject
public VoteManager(BtcWalletService btcWalletService, SquWalletService squWalletService, FeeService feeService, Storage<ArrayList<VoteItemCollection>> voteItemCollectionStorage) {
public VoteManager(BtcWalletService btcWalletService, SquWalletService squWalletService, FeeService feeService, Storage<ArrayList<VoteItemCollection>> voteItemCollectionsStorage) {
this.btcWalletService = btcWalletService;
this.squWalletService = squWalletService;
this.feeService = feeService;
this.voteItemCollectionStorage = voteItemCollectionStorage;
this.voteItemCollectionsStorage = voteItemCollectionsStorage;
ArrayList<VoteItemCollection> persisted = voteItemCollectionStorage.initAndGetPersistedWithFileName("VoteItemCollections");
ArrayList<VoteItemCollection> persisted = voteItemCollectionsStorage.initAndGetPersistedWithFileName("VoteItemCollections");
if (persisted != null)
voteItemCollections.addAll(persisted);
@ -150,7 +150,7 @@ public class VoteManager {
//TODO check equals code
if (!voteItemCollections.contains(voteItemCollection)) {
voteItemCollections.add(voteItemCollection);
voteItemCollectionStorage.queueUpForSave(voteItemCollections, 500);
voteItemCollectionsStorage.queueUpForSave(voteItemCollections, 500);
}
}

View file

@ -60,10 +60,10 @@ public class CompensationRequestDisplay {
categoryTextField.setText(data.category);
descriptionTextField.setText(data.description);
linkTextField.setText(data.link);
startDateTextField.setText(data.startDate.toString());
endDateTextField.setText(data.endDate.toString());
requestedBTCTextField.setText(data.requestedBtc.toPlainString());
btcAddressTextField.setText(data.btcAddress.toString());
startDateTextField.setText(data.getStartDate().toString());
endDateTextField.setText(data.getEndDate().toString());
requestedBTCTextField.setText(data.getRequestedBtc().toPlainString());
btcAddressTextField.setText(data.btcAddress);
}
public void clearForm() {

View file

@ -237,14 +237,14 @@ public class ActiveCompensationRequestView extends ActivatableView<SplitPane, Vo
public void updateItem(final CompensationRequest item, boolean empty) {
super.updateItem(item, empty);
if (item != null)
setText(formatter.formatDateTime(item.getCompensationRequestPayload().creationDate));
setText(formatter.formatDateTime(item.getCompensationRequestPayload().getCreationDate()));
else
setText("");
}
};
}
});
dateColumn.setComparator((o1, o2) -> o1.getCompensationRequestPayload().creationDate.compareTo(o2.getCompensationRequestPayload().creationDate));
dateColumn.setComparator((o1, o2) -> o1.getCompensationRequestPayload().getCreationDate().compareTo(o2.getCompensationRequestPayload().getCreationDate()));
tableView.getColumns().add(dateColumn);
tableView.getSortOrder().add(dateColumn);

View file

@ -18,6 +18,7 @@
package io.bitsquare.gui.main.dao.compensation.create;
import com.google.common.util.concurrent.FutureCallback;
import io.bitsquare.app.Version;
import io.bitsquare.btc.InsufficientFundsException;
import io.bitsquare.btc.exceptions.TransactionVerificationException;
import io.bitsquare.btc.exceptions.WalletException;
@ -25,8 +26,9 @@ import io.bitsquare.btc.provider.fee.FeeService;
import io.bitsquare.btc.wallet.BtcWalletService;
import io.bitsquare.btc.wallet.ChangeBelowDustException;
import io.bitsquare.btc.wallet.SquWalletService;
import io.bitsquare.common.ByteArrayUtils;
import io.bitsquare.common.crypto.KeyRing;
import io.bitsquare.common.util.MathUtils;
import io.bitsquare.common.util.Utilities;
import io.bitsquare.dao.compensation.CompensationRequestManager;
import io.bitsquare.dao.compensation.CompensationRequestPayload;
import io.bitsquare.gui.common.view.ActivatableView;
@ -40,14 +42,16 @@ import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.InsufficientMoneyException;
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.Utils;
import org.bitcoinj.crypto.DeterministicKey;
import org.bitcoinj.wallet.KeyChain;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable;
import javax.inject.Inject;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.PublicKey;
import java.util.Date;
import java.util.UUID;
@ -61,14 +65,17 @@ public class CreateCompensationRequestView extends ActivatableView<GridPane, Voi
private CompensationRequestDisplay CompensationRequestDisplay;
private Button createButton;
private final NodeAddress nodeAddress;
private final PublicKey p2pStorageSignaturePubKey;
private final SquWalletService squWalletService;
private final BtcWalletService btcWalletService;
private final FeeService feeService;
private final CompensationRequestManager compensationRequestManager;
private final P2PService p2PService;
private final BSFormatter btcFormatter;
@Nullable
private NodeAddress nodeAddress;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor, lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@ -80,9 +87,9 @@ public class CreateCompensationRequestView extends ActivatableView<GridPane, Voi
this.btcWalletService = btcWalletService;
this.feeService = feeService;
this.compensationRequestManager = compensationRequestManager;
this.p2PService = p2PService;
this.btcFormatter = btcFormatter;
nodeAddress = p2PService.getAddress();
p2pStorageSignaturePubKey = keyRing.getPubKeyRing().getSignaturePubKey();
}
@ -106,63 +113,96 @@ public class CreateCompensationRequestView extends ActivatableView<GridPane, Voi
Date startDate = new Date();
Date endDate = new Date();
CompensationRequestPayload compensationRequestPayload = new CompensationRequestPayload(UUID.randomUUID().toString(),
CompensationRequestDisplay.nameTextField.getText(),
CompensationRequestDisplay.titleTextField.getText(),
CompensationRequestDisplay.categoryTextField.getText(),
CompensationRequestDisplay.descriptionTextField.getText(),
CompensationRequestDisplay.linkTextField.getText(),
startDate,
endDate,
btcFormatter.parseToCoin(CompensationRequestDisplay.requestedBTCTextField.getText()),
CompensationRequestDisplay.btcAddressTextField.getText(),
nodeAddress,
p2pStorageSignaturePubKey,
squKeyPair.getPubKey()
);
Sha256Hash hash = Sha256Hash.of(ByteArrayUtils.objectToByteArray(compensationRequestPayload));
compensationRequestPayload.setSignature(squKeyPair.sign(hash).encodeToDER());
hash = Sha256Hash.of(ByteArrayUtils.objectToByteArray(compensationRequestPayload));
compensationRequestPayload.setHash(hash.getBytes());
// TODO can be null if we are still not full connected
nodeAddress = p2PService.getAddress();
if (nodeAddress != null) {
CompensationRequestPayload compensationRequestPayload = new CompensationRequestPayload(UUID.randomUUID().toString(),
CompensationRequestDisplay.nameTextField.getText(),
CompensationRequestDisplay.titleTextField.getText(),
CompensationRequestDisplay.categoryTextField.getText(),
CompensationRequestDisplay.descriptionTextField.getText(),
CompensationRequestDisplay.linkTextField.getText(),
startDate,
endDate,
btcFormatter.parseToCoin(CompensationRequestDisplay.requestedBTCTextField.getText()),
CompensationRequestDisplay.btcAddressTextField.getText(),
nodeAddress,
p2pStorageSignaturePubKey
);
// We get the JSON of the object excluding signature and feeTxId
String payloadAsJson = Utilities.objectToJson(compensationRequestPayload);
// Signs a text message using the standard Bitcoin messaging signing format and returns the signature as a base64
// encoded string.
String signature = squKeyPair.signMessage(payloadAsJson);
compensationRequestPayload.setSignature(signature);
try {
Coin createCompensationRequestFee = feeService.getCreateCompensationRequestFee();
Transaction preparedSendTx = squWalletService.getPreparedBurnFeeTx(createCompensationRequestFee);
Transaction txWithBtcFee = btcWalletService.completePreparedSquTx(preparedSendTx, false, hash.getBytes());
Transaction signedTx = squWalletService.signTx(txWithBtcFee);
squWalletService.commitTx(txWithBtcFee);
// We need to create another instance, otherwise the tx would trigger an invalid state exception
// if it gets committed 2 times
btcWalletService.commitTx(btcWalletService.getClonedTransaction(txWithBtcFee));
squWalletService.broadcastTx(signedTx, new FutureCallback<Transaction>() {
@Override
public void onSuccess(@Nullable Transaction transaction) {
checkNotNull(transaction, "Transaction must not be null at signAndBroadcastCompensationRequestFeeTx callback.");
compensationRequestPayload.setFeeTxId(transaction.getHashAsString());
publishToP2PNetwork(compensationRequestPayload);
CompensationRequestDisplay.clearForm();
new Popup<>().confirmation("Your compensationRequestPayload has been successfully published.").show();
}
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
String dataAndSig = payloadAsJson + signature;
byte[] dataAndSigAsBytes = dataAndSig.getBytes();
outputStream.write(Version.COMP_REQUEST_VERSION);
outputStream.write(Utils.sha256hash160(dataAndSigAsBytes));
byte hash[] = outputStream.toByteArray();
//TODO should we store the hash in the compensationRequestPayload object?
@Override
public void onFailure(@NotNull Throwable t) {
log.error(t.toString());
new Popup<>().warning(t.toString()).show();
}
});
} catch (InsufficientFundsException |
TransactionVerificationException | WalletException | InsufficientMoneyException | ChangeBelowDustException e) {
log.error(e.toString());
e.printStackTrace();
new Popup<>().warning(e.toString()).show();
Coin createCompensationRequestFee = feeService.getCreateCompensationRequestFee();
Transaction preparedSendTx = squWalletService.getPreparedBurnFeeTx(createCompensationRequestFee);
//TODO 1 Btc output (small payment to own compensation receiving address)
Transaction txWithBtcFee = btcWalletService.completePreparedSquTx(preparedSendTx, false, hash);
Transaction signedTx = squWalletService.signTx(txWithBtcFee);
Coin miningFee = signedTx.getFee();
int txSize = signedTx.bitcoinSerialize().length;
new Popup().headLine("Confirm compensation request fee payment transaction")
.confirmation("Voting fee: " + btcFormatter.formatCoinWithCode(createCompensationRequestFee) + "\n" +
"Mining fee: " + btcFormatter.formatCoinWithCode(miningFee) + " (" +
MathUtils.roundDouble(((double) miningFee.value / (double) txSize), 2) +
" Satoshis/byte)\n" +
"Transaction size: " + (txSize / 1000d) + " Kb\n\n" +
"Are you sure you want to send the transaction?")
.actionButtonText("Yes")
.onAction(() -> {
try {
squWalletService.commitTx(txWithBtcFee);
// We need to create another instance, otherwise the tx would trigger an invalid state exception
// if it gets committed 2 times
btcWalletService.commitTx(btcWalletService.getClonedTransaction(txWithBtcFee));
squWalletService.broadcastTx(signedTx, new FutureCallback<Transaction>() {
@Override
public void onSuccess(@Nullable Transaction transaction) {
checkNotNull(transaction, "Transaction must not be null at broadcastTx callback.");
compensationRequestPayload.setFeeTxId(transaction.getHashAsString());
compensationRequestManager.addToP2PNetwork(compensationRequestPayload);
CompensationRequestDisplay.clearForm();
new Popup<>().confirmation("Your transaction has been successfully published.").show();
}
@Override
public void onFailure(@NotNull Throwable t) {
log.error(t.toString());
new Popup<>().warning(t.toString()).show();
}
});
} catch (WalletException | TransactionVerificationException e) {
log.error(e.toString());
e.printStackTrace();
new Popup<>().warning(e.toString());
}
})
.closeButtonText("Cancel")
.show();
} catch (InsufficientFundsException | IOException |
TransactionVerificationException | WalletException | InsufficientMoneyException | ChangeBelowDustException e) {
log.error(e.toString());
e.printStackTrace();
new Popup<>().warning(e.toString()).show();
}
} else {
//TODO check if that can happen
new Popup<>().warning("Your node address is not known yet. Please try again after your hidden service is published.").show();
}
});
}
private void publishToP2PNetwork(CompensationRequestPayload compensationRequestPayload) {
compensationRequestManager.addToP2PNetwork(compensationRequestPayload);
}
@Override
protected void deactivate() {
createButton.setOnAction(null);

View file

@ -109,57 +109,64 @@ public class VoteView extends ActivatableView<GridPane, Void> {
voteButton = addButtonAfterGroup(root, ++gridRow, "Vote");
voteButton.setOnAction(event -> {
byte[] hash = voteManager.calculateHash(voteItemCollection);
if (hash.length > 0) {
try {
Coin votingTxFee = feeService.getVotingTxFee();
Transaction preparedVotingTx = squWalletService.getPreparedBurnFeeTx(votingTxFee);
Transaction txWithBtcFee = btcWalletService.completePreparedSquTx(preparedVotingTx, false, hash);
Transaction signedTx = squWalletService.signTx(txWithBtcFee);
Coin miningFee = signedTx.getFee();
int txSize = signedTx.bitcoinSerialize().length;
new Popup().headLine("Confirm withdrawal request")
.confirmation("Voting fee: " + btcFormatter.formatCoinWithCode(votingTxFee) + "\n" +
"Mining fee: " + btcFormatter.formatCoinWithCode(miningFee) + " (" +
MathUtils.roundDouble(((double) miningFee.value / (double) txSize), 2) +
" Satoshis/byte)\n" +
"Transaction size: " + (txSize / 1000d) + " Kb\n\n" +
"Are you sure you want to send the vote transaction?")
.actionButtonText("Yes")
.onAction(() -> {
try {
squWalletService.commitTx(txWithBtcFee);
// We need to create another instance, otherwise the tx would trigger an invalid state exception
// if it gets committed 2 times
btcWalletService.commitTx(btcWalletService.getClonedTransaction(txWithBtcFee));
squWalletService.broadcastTx(signedTx, new FutureCallback<Transaction>() {
@Override
public void onSuccess(@Nullable Transaction transaction) {
checkNotNull(transaction, "Transaction must not be null at doSend callback.");
log.error("tx successful published" + transaction.getHashAsString());
}
if (!voteItemCollection.isMyVote()) {
byte[] hash = voteManager.calculateHash(voteItemCollection);
if (hash.length > 0) {
try {
Coin votingTxFee = feeService.getVotingTxFee();
Transaction preparedVotingTx = squWalletService.getPreparedBurnFeeTx(votingTxFee);
Transaction txWithBtcFee = btcWalletService.completePreparedSquTx(preparedVotingTx, false, hash);
Transaction signedTx = squWalletService.signTx(txWithBtcFee);
Coin miningFee = signedTx.getFee();
int txSize = signedTx.bitcoinSerialize().length;
new Popup().headLine("Confirm voting fee payment transaction")
.confirmation("Voting fee: " + btcFormatter.formatCoinWithCode(votingTxFee) + "\n" +
"Mining fee: " + btcFormatter.formatCoinWithCode(miningFee) + " (" +
MathUtils.roundDouble(((double) miningFee.value / (double) txSize), 2) +
" Satoshis/byte)\n" +
"Transaction size: " + (txSize / 1000d) + " Kb\n\n" +
"Are you sure you want to send the transaction?")
.actionButtonText("Yes")
.onAction(() -> {
try {
squWalletService.commitTx(txWithBtcFee);
// We need to create another instance, otherwise the tx would trigger an invalid state exception
// if it gets committed 2 times
btcWalletService.commitTx(btcWalletService.getClonedTransaction(txWithBtcFee));
squWalletService.broadcastTx(signedTx, new FutureCallback<Transaction>() {
@Override
public void onSuccess(@Nullable Transaction transaction) {
checkNotNull(transaction, "Transaction must not be null at doSend callback.");
log.error("tx successful published" + transaction.getHashAsString());
new Popup<>().confirmation("Your transaction has been successfully published.").show();
voteItemCollection.setIsMyVote(true);
}
@Override
public void onFailure(@NotNull Throwable t) {
new Popup<>().warning(t.toString()).show();
}
});
} catch (WalletException | TransactionVerificationException e) {
log.error(e.toString());
e.printStackTrace();
new Popup<>().warning(e.toString());
}
})
.closeButtonText("Cancel")
.show();
} catch (InsufficientMoneyException | WalletException | TransactionVerificationException |
ChangeBelowDustException | InsufficientFundsException e) {
log.error(e.toString());
e.printStackTrace();
new Popup<>().warning(e.toString()).show();
@Override
public void onFailure(@NotNull Throwable t) {
new Popup<>().warning(t.toString()).show();
}
});
} catch (WalletException | TransactionVerificationException e) {
log.error(e.toString());
e.printStackTrace();
new Popup<>().warning(e.toString());
}
})
.closeButtonText("Cancel")
.show();
} catch (InsufficientMoneyException | WalletException | TransactionVerificationException |
ChangeBelowDustException | InsufficientFundsException e) {
log.error(e.toString());
e.printStackTrace();
new Popup<>().warning(e.toString()).show();
}
} else {
new Popup<>().warning("You did not vote on any entry.").show();
}
} else {
new Popup<>().warning("You did not vote on any entry.").show();
//TODO
new Popup<>().warning("You voted already.").show();
}
});
}