mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-25 07:27:18 +01:00
Use version byte and ripemd160 hash of json for comp. data. Use only primitive data in comp. data.
This commit is contained in:
parent
5c9c14255c
commit
5dc00eb427
8 changed files with 259 additions and 187 deletions
|
@ -80,4 +80,7 @@ public class Version {
|
|||
", getP2PNetworkId()=" + getP2PMessageVersion() +
|
||||
'}');
|
||||
}
|
||||
|
||||
public static final byte COMP_REQUEST_VERSION = (byte) 0x01;
|
||||
|
||||
}
|
||||
|
|
|
@ -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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue