use byte[] for signatures instead of strings

This commit is contained in:
woodser 2023-03-11 16:09:22 -05:00
parent ead70751dc
commit 4650003838
23 changed files with 265 additions and 255 deletions

View file

@ -20,12 +20,15 @@ package haveno.core.offer;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializationContext;
import com.google.protobuf.ByteString;
import haveno.common.crypto.Hash; import haveno.common.crypto.Hash;
import haveno.common.crypto.PubKeyRing; import haveno.common.crypto.PubKeyRing;
import haveno.common.proto.ProtoUtil; import haveno.common.proto.ProtoUtil;
import haveno.common.util.CollectionUtils; import haveno.common.util.CollectionUtils;
import haveno.common.util.Hex; import haveno.common.util.Hex;
import haveno.common.util.JsonExclude; import haveno.common.util.JsonExclude;
import haveno.common.util.Utilities;
import haveno.network.p2p.NodeAddress; import haveno.network.p2p.NodeAddress;
import haveno.network.p2p.storage.payload.ExpirablePayload; import haveno.network.p2p.storage.payload.ExpirablePayload;
import haveno.network.p2p.storage.payload.ProtectedStoragePayload; import haveno.network.p2p.storage.payload.ProtectedStoragePayload;
@ -81,7 +84,7 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
protected NodeAddress arbitratorSigner; protected NodeAddress arbitratorSigner;
@Setter @Setter
@Nullable @Nullable
protected String arbitratorSignature; protected byte[] arbitratorSignature;
@Setter @Setter
@Nullable @Nullable
protected List<String> reserveTxKeyImages; protected List<String> reserveTxKeyImages;
@ -191,7 +194,7 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
@Nullable Map<String, String> extraDataMap, @Nullable Map<String, String> extraDataMap,
int protocolVersion, int protocolVersion,
@Nullable NodeAddress arbitratorSigner, @Nullable NodeAddress arbitratorSigner,
@Nullable String arbitratorSignature, @Nullable byte[] arbitratorSignature,
@Nullable List<String> reserveTxKeyImages) { @Nullable List<String> reserveTxKeyImages) {
this.id = id; this.id = id;
this.date = date; this.date = date;
@ -302,7 +305,7 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
Optional.ofNullable(acceptedCountryCodes).ifPresent(builder::addAllAcceptedCountryCodes); Optional.ofNullable(acceptedCountryCodes).ifPresent(builder::addAllAcceptedCountryCodes);
Optional.ofNullable(hashOfChallenge).ifPresent(builder::setHashOfChallenge); Optional.ofNullable(hashOfChallenge).ifPresent(builder::setHashOfChallenge);
Optional.ofNullable(extraDataMap).ifPresent(builder::putAllExtraData); Optional.ofNullable(extraDataMap).ifPresent(builder::putAllExtraData);
Optional.ofNullable(arbitratorSignature).ifPresent(builder::setArbitratorSignature); Optional.ofNullable(arbitratorSignature).ifPresent(e -> builder.setArbitratorSignature(ByteString.copyFrom(e)));
Optional.ofNullable(reserveTxKeyImages).ifPresent(builder::addAllReserveTxKeyImages); Optional.ofNullable(reserveTxKeyImages).ifPresent(builder::addAllReserveTxKeyImages);
return protobuf.StoragePayload.newBuilder().setOfferPayload(builder).build(); return protobuf.StoragePayload.newBuilder().setOfferPayload(builder).build();
@ -352,7 +355,7 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
extraDataMapMap, extraDataMapMap,
proto.getProtocolVersion(), proto.getProtocolVersion(),
proto.hasArbitratorSigner() ? NodeAddress.fromProto(proto.getArbitratorSigner()) : null, proto.hasArbitratorSigner() ? NodeAddress.fromProto(proto.getArbitratorSigner()) : null,
ProtoUtil.stringOrNullFromProto(proto.getArbitratorSignature()), ProtoUtil.byteArrayOrNullFromProto(proto.getArbitratorSignature()),
proto.getReserveTxKeyImagesList() == null ? null : new ArrayList<String>(proto.getReserveTxKeyImagesList())); proto.getReserveTxKeyImagesList() == null ? null : new ArrayList<String>(proto.getReserveTxKeyImagesList()));
} }
@ -375,8 +378,6 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
",\r\n pubKeyRing=" + pubKeyRing + ",\r\n pubKeyRing=" + pubKeyRing +
",\r\n hash=" + (hash != null ? Hex.encode(hash) : "null") + ",\r\n hash=" + (hash != null ? Hex.encode(hash) : "null") +
",\r\n extraDataMap=" + extraDataMap + ",\r\n extraDataMap=" + extraDataMap +
",\r\n arbitratorSigner=" + arbitratorSigner +
",\r\n arbitratorSignature=" + arbitratorSignature +
",\r\n reserveTxKeyImages=" + reserveTxKeyImages + ",\r\n reserveTxKeyImages=" + reserveTxKeyImages +
",\r\n marketPriceMargin=" + marketPriceMarginPct + ",\r\n marketPriceMargin=" + marketPriceMarginPct +
",\r\n useMarketBasedPrice=" + useMarketBasedPrice + ",\r\n useMarketBasedPrice=" + useMarketBasedPrice +
@ -398,7 +399,7 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
",\r\n isPrivateOffer=" + isPrivateOffer + ",\r\n isPrivateOffer=" + isPrivateOffer +
",\r\n hashOfChallenge='" + hashOfChallenge + '\'' + ",\r\n hashOfChallenge='" + hashOfChallenge + '\'' +
",\n arbitratorSigner=" + arbitratorSigner + ",\n arbitratorSigner=" + arbitratorSigner +
",\n arbitratorSignature=" + arbitratorSignature + ",\n arbitratorSignature=" + Utilities.bytesAsHexString(arbitratorSignature) +
"\r\n} "; "\r\n} ";
} }

View file

@ -25,7 +25,6 @@ import haveno.common.app.Capability;
import haveno.common.app.Version; import haveno.common.app.Version;
import haveno.common.crypto.KeyRing; import haveno.common.crypto.KeyRing;
import haveno.common.crypto.PubKeyRing; import haveno.common.crypto.PubKeyRing;
import haveno.common.crypto.Sig;
import haveno.common.handlers.ErrorMessageHandler; import haveno.common.handlers.ErrorMessageHandler;
import haveno.common.handlers.ResultHandler; import haveno.common.handlers.ResultHandler;
import haveno.common.persistence.PersistenceManager; import haveno.common.persistence.PersistenceManager;
@ -1000,7 +999,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
// arbitrator signs offer to certify they have valid reserve tx // arbitrator signs offer to certify they have valid reserve tx
String offerPayloadAsJson = JsonUtil.objectToJson(request.getOfferPayload()); String offerPayloadAsJson = JsonUtil.objectToJson(request.getOfferPayload());
String signature = Sig.sign(keyRing.getSignatureKeyPair().getPrivate(), offerPayloadAsJson); byte[] signature = HavenoUtils.sign(keyRing, offerPayloadAsJson);
OfferPayload signedOfferPayload = request.getOfferPayload(); OfferPayload signedOfferPayload = request.getOfferPayload();
signedOfferPayload.setArbitratorSignature(signature); signedOfferPayload.setArbitratorSignature(signature);
@ -1119,7 +1118,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
try { try {
Optional<OpenOffer> openOfferOptional = getOpenOfferById(request.offerId); Optional<OpenOffer> openOfferOptional = getOpenOfferById(request.offerId);
AvailabilityResult availabilityResult; AvailabilityResult availabilityResult;
String makerSignature = null; byte[] makerSignature = null;
if (openOfferOptional.isPresent()) { if (openOfferOptional.isPresent()) {
OpenOffer openOffer = openOfferOptional.get(); OpenOffer openOffer = openOfferOptional.get();
if (!apiUserDeniedByOffer(request)) { if (!apiUserDeniedByOffer(request)) {
@ -1130,7 +1129,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
// maker signs taker's request // maker signs taker's request
String tradeRequestAsJson = JsonUtil.objectToJson(request.getTradeRequest()); String tradeRequestAsJson = JsonUtil.objectToJson(request.getTradeRequest());
makerSignature = Sig.sign(keyRing.getSignatureKeyPair().getPrivate(), tradeRequestAsJson); makerSignature = HavenoUtils.sign(keyRing, tradeRequestAsJson);
try { try {
// Check also tradePrice to avoid failures after taker fee is paid caused by a too big difference // Check also tradePrice to avoid failures after taker fee is paid caused by a too big difference

View file

@ -17,10 +17,14 @@
package haveno.core.offer; package haveno.core.offer;
import haveno.common.proto.ProtoUtil;
import haveno.common.proto.persistable.PersistablePayload; import haveno.common.proto.persistable.PersistablePayload;
import haveno.core.util.JsonUtil; import haveno.core.util.JsonUtil;
import java.util.List; import java.util.List;
import com.google.protobuf.ByteString;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -48,7 +52,7 @@ public final class SignedOffer implements PersistablePayload {
@Getter @Getter
private final long reserveTxMinerFee; private final long reserveTxMinerFee;
@Getter @Getter
private final String arbitratorSignature; private final byte[] arbitratorSignature;
public SignedOffer(long timeStamp, public SignedOffer(long timeStamp,
int traderId, int traderId,
@ -59,7 +63,7 @@ public final class SignedOffer implements PersistablePayload {
String reserveTxHex, String reserveTxHex,
List<String> reserveTxKeyImages, List<String> reserveTxKeyImages,
long reserveTxMinerFee, long reserveTxMinerFee,
String arbitratorSignature) { byte[] arbitratorSignature) {
this.timeStamp = timeStamp; this.timeStamp = timeStamp;
this.traderId = traderId; this.traderId = traderId;
this.offerId = offerId; this.offerId = offerId;
@ -88,7 +92,7 @@ public final class SignedOffer implements PersistablePayload {
.setReserveTxHex(reserveTxHex) .setReserveTxHex(reserveTxHex)
.addAllReserveTxKeyImages(reserveTxKeyImages) .addAllReserveTxKeyImages(reserveTxKeyImages)
.setReserveTxMinerFee(reserveTxMinerFee) .setReserveTxMinerFee(reserveTxMinerFee)
.setArbitratorSignature(arbitratorSignature); .setArbitratorSignature(ByteString.copyFrom(arbitratorSignature));
return builder.build(); return builder.build();
} }
@ -102,7 +106,7 @@ public final class SignedOffer implements PersistablePayload {
proto.getReserveTxHex(), proto.getReserveTxHex(),
proto.getReserveTxKeyImagesList(), proto.getReserveTxKeyImagesList(),
proto.getReserveTxMinerFee(), proto.getReserveTxMinerFee(),
proto.getArbitratorSignature()); ProtoUtil.byteArrayOrNullFromProto(proto.getArbitratorSignature()));
} }

View file

@ -61,7 +61,7 @@ public class OfferAvailabilityModel implements Model {
@Nullable @Nullable
@Setter @Setter
@Getter @Getter
private String makerSignature; private byte[] makerSignature;
// Added in v1.5.5 // Added in v1.5.5
@Getter @Getter

View file

@ -17,9 +17,7 @@
package haveno.core.offer.availability.tasks; package haveno.core.offer.availability.tasks;
import com.google.common.base.Charsets;
import haveno.common.app.Version; import haveno.common.app.Version;
import haveno.common.crypto.Sig;
import haveno.common.taskrunner.Task; import haveno.common.taskrunner.Task;
import haveno.common.taskrunner.TaskRunner; import haveno.common.taskrunner.TaskRunner;
import haveno.core.monetary.Price; import haveno.core.monetary.Price;
@ -59,7 +57,7 @@ public class SendOfferAvailabilityRequest extends Task<OfferAvailabilityModel> {
String payoutAddress = walletService.getOrCreateAddressEntry(offer.getId(), XmrAddressEntry.Context.TRADE_PAYOUT).getAddressString(); // reserve new payout address String payoutAddress = walletService.getOrCreateAddressEntry(offer.getId(), XmrAddressEntry.Context.TRADE_PAYOUT).getAddressString(); // reserve new payout address
// taker signs offer using offer id as nonce to avoid challenge protocol // taker signs offer using offer id as nonce to avoid challenge protocol
byte[] sig = Sig.sign(model.getP2PService().getKeyRing().getSignatureKeyPair().getPrivate(), offer.getId().getBytes(Charsets.UTF_8)); byte[] sig = HavenoUtils.sign(model.getP2PService().getKeyRing(), offer.getId());
// get price // get price
Price price = offer.getPrice(); Price price = offer.getPrice();

View file

@ -31,6 +31,8 @@ import lombok.Value;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import com.google.protobuf.ByteString;
// We add here the SupportedCapabilitiesMessage interface as that message always predates a direct connection // We add here the SupportedCapabilitiesMessage interface as that message always predates a direct connection
// to the trading peer // to the trading peer
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ -41,11 +43,11 @@ public final class OfferAvailabilityResponse extends OfferMessage implements Sup
private final Capabilities supportedCapabilities; private final Capabilities supportedCapabilities;
@Nullable @Nullable
private final String makerSignature; private byte[] makerSignature;
public OfferAvailabilityResponse(String offerId, public OfferAvailabilityResponse(String offerId,
AvailabilityResult availabilityResult, AvailabilityResult availabilityResult,
String makerSignature) { @Nullable byte[] makerSignature) {
this(offerId, this(offerId,
availabilityResult, availabilityResult,
Capabilities.app, Capabilities.app,
@ -64,7 +66,7 @@ public final class OfferAvailabilityResponse extends OfferMessage implements Sup
@Nullable Capabilities supportedCapabilities, @Nullable Capabilities supportedCapabilities,
String messageVersion, String messageVersion,
@Nullable String uid, @Nullable String uid,
String makerSignature) { byte[] makerSignature) {
super(messageVersion, offerId, uid); super(messageVersion, offerId, uid);
this.availabilityResult = availabilityResult; this.availabilityResult = availabilityResult;
this.supportedCapabilities = supportedCapabilities; this.supportedCapabilities = supportedCapabilities;
@ -79,7 +81,7 @@ public final class OfferAvailabilityResponse extends OfferMessage implements Sup
Optional.ofNullable(supportedCapabilities).ifPresent(e -> builder.addAllSupportedCapabilities(Capabilities.toIntList(supportedCapabilities))); Optional.ofNullable(supportedCapabilities).ifPresent(e -> builder.addAllSupportedCapabilities(Capabilities.toIntList(supportedCapabilities)));
Optional.ofNullable(uid).ifPresent(e -> builder.setUid(uid)); Optional.ofNullable(uid).ifPresent(e -> builder.setUid(uid));
Optional.ofNullable(makerSignature).ifPresent(e -> builder.setMakerSignature(makerSignature)); Optional.ofNullable(makerSignature).ifPresent(e -> builder.setMakerSignature(ByteString.copyFrom(e)));
return getNetworkEnvelopeBuilder() return getNetworkEnvelopeBuilder()
.setOfferAvailabilityResponse(builder) .setOfferAvailabilityResponse(builder)
@ -92,6 +94,6 @@ public final class OfferAvailabilityResponse extends OfferMessage implements Sup
Capabilities.fromIntList(proto.getSupportedCapabilitiesList()), Capabilities.fromIntList(proto.getSupportedCapabilitiesList()),
messageVersion, messageVersion,
proto.getUid().isEmpty() ? null : proto.getUid(), proto.getUid().isEmpty() ? null : proto.getUid(),
proto.getMakerSignature().isEmpty() ? null : proto.getMakerSignature()); ProtoUtil.byteArrayOrNullFromProto(proto.getMakerSignature()));
} }
} }

View file

@ -104,9 +104,9 @@ public final class Dispute implements NetworkPayload, PersistablePayload {
private final String payoutTxId; private final String payoutTxId;
private String contractAsJson; private String contractAsJson;
@Nullable @Nullable
private final String makerContractSignature; private final byte[] makerContractSignature;
@Nullable @Nullable
private final String takerContractSignature; private final byte[] takerContractSignature;
private final PubKeyRing agentPubKeyRing; // dispute agent private final PubKeyRing agentPubKeyRing; // dispute agent
private final boolean isSupportTicket; private final boolean isSupportTicket;
private final ObservableList<ChatMessage> chatMessages = FXCollections.observableArrayList(); private final ObservableList<ChatMessage> chatMessages = FXCollections.observableArrayList();
@ -179,8 +179,8 @@ public final class Dispute implements NetworkPayload, PersistablePayload {
@Nullable String depositTxId, @Nullable String depositTxId,
@Nullable String payoutTxId, @Nullable String payoutTxId,
String contractAsJson, String contractAsJson,
@Nullable String makerContractSignature, @Nullable byte[] makerContractSignature,
@Nullable String takerContractSignature, @Nullable byte[] takerContractSignature,
@Nullable PaymentAccountPayload makerPaymentAccountPayload, @Nullable PaymentAccountPayload makerPaymentAccountPayload,
@Nullable PaymentAccountPayload takerPaymentAccountPayload, @Nullable PaymentAccountPayload takerPaymentAccountPayload,
PubKeyRing agentPubKeyRing, PubKeyRing agentPubKeyRing,
@ -251,8 +251,8 @@ public final class Dispute implements NetworkPayload, PersistablePayload {
Optional.ofNullable(depositTxId).ifPresent(builder::setDepositTxId); Optional.ofNullable(depositTxId).ifPresent(builder::setDepositTxId);
Optional.ofNullable(payoutTxId).ifPresent(builder::setPayoutTxId); Optional.ofNullable(payoutTxId).ifPresent(builder::setPayoutTxId);
Optional.ofNullable(disputePayoutTxId).ifPresent(builder::setDisputePayoutTxId); Optional.ofNullable(disputePayoutTxId).ifPresent(builder::setDisputePayoutTxId);
Optional.ofNullable(makerContractSignature).ifPresent(builder::setMakerContractSignature); Optional.ofNullable(makerContractSignature).ifPresent(e -> builder.setMakerContractSignature(ByteString.copyFrom(e)));
Optional.ofNullable(takerContractSignature).ifPresent(builder::setTakerContractSignature); Optional.ofNullable(takerContractSignature).ifPresent(e -> builder.setTakerContractSignature(ByteString.copyFrom(e)));
Optional.ofNullable(makerPaymentAccountPayload).ifPresent(e -> builder.setMakerPaymentAccountPayload((protobuf.PaymentAccountPayload) makerPaymentAccountPayload.toProtoMessage())); Optional.ofNullable(makerPaymentAccountPayload).ifPresent(e -> builder.setMakerPaymentAccountPayload((protobuf.PaymentAccountPayload) makerPaymentAccountPayload.toProtoMessage()));
Optional.ofNullable(takerPaymentAccountPayload).ifPresent(e -> builder.setTakerPaymentAccountPayload((protobuf.PaymentAccountPayload) takerPaymentAccountPayload.toProtoMessage())); Optional.ofNullable(takerPaymentAccountPayload).ifPresent(e -> builder.setTakerPaymentAccountPayload((protobuf.PaymentAccountPayload) takerPaymentAccountPayload.toProtoMessage()));
Optional.ofNullable(disputeResultProperty.get()).ifPresent(result -> builder.setDisputeResult(disputeResultProperty.get().toProtoMessage())); Optional.ofNullable(disputeResultProperty.get()).ifPresent(result -> builder.setDisputeResult(disputeResultProperty.get().toProtoMessage()));
@ -281,8 +281,8 @@ public final class Dispute implements NetworkPayload, PersistablePayload {
ProtoUtil.stringOrNullFromProto(proto.getDepositTxId()), ProtoUtil.stringOrNullFromProto(proto.getDepositTxId()),
ProtoUtil.stringOrNullFromProto(proto.getPayoutTxId()), ProtoUtil.stringOrNullFromProto(proto.getPayoutTxId()),
proto.getContractAsJson(), proto.getContractAsJson(),
ProtoUtil.stringOrNullFromProto(proto.getMakerContractSignature()), ProtoUtil.byteArrayOrNullFromProto(proto.getMakerContractSignature()),
ProtoUtil.stringOrNullFromProto(proto.getTakerContractSignature()), ProtoUtil.byteArrayOrNullFromProto(proto.getTakerContractSignature()),
proto.hasMakerPaymentAccountPayload() ? coreProtoResolver.fromProto(proto.getMakerPaymentAccountPayload()) : null, proto.hasMakerPaymentAccountPayload() ? coreProtoResolver.fromProto(proto.getMakerPaymentAccountPayload()) : null,
proto.hasTakerPaymentAccountPayload() ? coreProtoResolver.fromProto(proto.getTakerPaymentAccountPayload()) : null, proto.hasTakerPaymentAccountPayload() ? coreProtoResolver.fromProto(proto.getTakerPaymentAccountPayload()) : null,
PubKeyRing.fromProto(proto.getAgentPubKeyRing()), PubKeyRing.fromProto(proto.getAgentPubKeyRing()),
@ -524,8 +524,8 @@ public final class Dispute implements NetworkPayload, PersistablePayload {
",\n depositTxId='" + depositTxId + '\'' + ",\n depositTxId='" + depositTxId + '\'' +
",\n payoutTxId='" + payoutTxId + '\'' + ",\n payoutTxId='" + payoutTxId + '\'' +
",\n contractAsJson='" + contractAsJson + '\'' + ",\n contractAsJson='" + contractAsJson + '\'' +
",\n makerContractSignature='" + makerContractSignature + '\'' + ",\n makerContractSignature='" + Utilities.bytesAsHexString(makerContractSignature) + '\'' +
",\n takerContractSignature='" + takerContractSignature + '\'' + ",\n takerContractSignature='" + Utilities.bytesAsHexString(takerContractSignature) + '\'' +
",\n agentPubKeyRing=" + agentPubKeyRing + ",\n agentPubKeyRing=" + agentPubKeyRing +
",\n isSupportTicket=" + isSupportTicket + ",\n isSupportTicket=" + isSupportTicket +
",\n chatMessages=" + chatMessages + ",\n chatMessages=" + chatMessages +

View file

@ -17,16 +17,14 @@
package haveno.core.support.dispute; package haveno.core.support.dispute;
import haveno.common.crypto.CryptoException;
import haveno.common.crypto.Hash; import haveno.common.crypto.Hash;
import haveno.common.crypto.Sig;
import haveno.common.util.Utilities; import haveno.common.util.Utilities;
import haveno.core.locale.Res; import haveno.core.locale.Res;
import haveno.core.support.dispute.agent.DisputeAgent; import haveno.core.support.dispute.agent.DisputeAgent;
import haveno.core.support.dispute.arbitration.arbitrator.ArbitratorManager; import haveno.core.support.dispute.arbitration.arbitrator.ArbitratorManager;
import haveno.core.trade.HavenoUtils;
import haveno.network.p2p.NodeAddress; import haveno.network.p2p.NodeAddress;
import java.security.KeyPair; import java.security.KeyPair;
import java.security.PublicKey;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -46,10 +44,10 @@ public class DisputeSummaryVerification {
KeyPair signatureKeyPair = disputeManager.getSignatureKeyPair(); KeyPair signatureKeyPair = disputeManager.getSignatureKeyPair();
String sigAsHex; String sigAsHex;
try { try {
byte[] signature = Sig.sign(signatureKeyPair.getPrivate(), hash); byte[] signature = HavenoUtils.sign(signatureKeyPair.getPrivate(), hash);
sigAsHex = Utilities.encodeToHex(signature); sigAsHex = Utilities.encodeToHex(signature);
disputeResult.setArbitratorSignature(signature); disputeResult.setArbitratorSignature(signature);
} catch (CryptoException e) { } catch (Exception e) {
sigAsHex = "Signing failed"; sigAsHex = "Signing failed";
} }
@ -69,19 +67,13 @@ public class DisputeSummaryVerification {
NodeAddress nodeAddress = new NodeAddress(fullAddress); NodeAddress nodeAddress = new NodeAddress(fullAddress);
DisputeAgent disputeAgent = arbitratorMediator.getDisputeAgentByNodeAddress(nodeAddress).orElse(null); DisputeAgent disputeAgent = arbitratorMediator.getDisputeAgentByNodeAddress(nodeAddress).orElse(null);
checkNotNull(disputeAgent, "Dispute agent is null"); checkNotNull(disputeAgent, "Dispute agent is null");
PublicKey pubKey = disputeAgent.getPubKeyRing().getSignaturePubKey();
String sigString = parts[1].split(SEPARATOR2)[0]; String sigString = parts[1].split(SEPARATOR2)[0];
byte[] sig = Utilities.decodeFromHex(sigString); byte[] sig = Utilities.decodeFromHex(sigString);
byte[] hash = Hash.getSha256Hash(textToSign); byte[] hash = Hash.getSha256Hash(textToSign);
try { try {
boolean result = Sig.verify(pubKey, hash, sig); HavenoUtils.verifySignature(disputeAgent.getPubKeyRing(), hash, sig);
if (result) { } catch (Exception e) {
return;
} else {
throw new IllegalArgumentException(Res.get("support.sigCheck.popup.failed"));
}
} catch (CryptoException e) {
throw new IllegalArgumentException(Res.get("support.sigCheck.popup.failed")); throw new IllegalArgumentException(Res.get("support.sigCheck.popup.failed"));
} }
} catch (Throwable e) { } catch (Throwable e) {

View file

@ -18,12 +18,11 @@
package haveno.core.support.dispute; package haveno.core.support.dispute;
import haveno.common.config.Config; import haveno.common.config.Config;
import haveno.common.crypto.CryptoException;
import haveno.common.crypto.Hash; import haveno.common.crypto.Hash;
import haveno.common.crypto.Sig;
import haveno.common.util.Tuple3; import haveno.common.util.Tuple3;
import haveno.core.support.SupportType; import haveno.core.support.SupportType;
import haveno.core.trade.Contract; import haveno.core.trade.Contract;
import haveno.core.trade.HavenoUtils;
import haveno.core.trade.Trade; import haveno.core.trade.Trade;
import haveno.core.util.JsonUtil; import haveno.core.util.JsonUtil;
import haveno.core.util.validation.RegexValidatorFactory; import haveno.core.util.validation.RegexValidatorFactory;
@ -64,23 +63,11 @@ public class DisputeValidation {
checkArgument(Arrays.equals(Objects.requireNonNull(dispute.getContractHash()), Hash.getSha256Hash(checkNotNull(dispute.getContractAsJson()))), checkArgument(Arrays.equals(Objects.requireNonNull(dispute.getContractHash()), Hash.getSha256Hash(checkNotNull(dispute.getContractAsJson()))),
"Invalid contractHash"); "Invalid contractHash");
try {
// Only the dispute opener has set the signature // Only the dispute opener has set the signature
String makerContractSignature = dispute.getMakerContractSignature(); byte[] makerContractSignature = dispute.getMakerContractSignature();
if (makerContractSignature != null) { if (makerContractSignature != null) HavenoUtils.verifySignature(contract.getMakerPubKeyRing(), dispute.getContractAsJson(), makerContractSignature);
Sig.verify(contract.getMakerPubKeyRing().getSignaturePubKey(), byte[] takerContractSignature = dispute.getTakerContractSignature();
dispute.getContractAsJson(), if (takerContractSignature != null) HavenoUtils.verifySignature(contract.getTakerPubKeyRing(), dispute.getContractAsJson(), takerContractSignature);
makerContractSignature);
}
String takerContractSignature = dispute.getTakerContractSignature();
if (takerContractSignature != null) {
Sig.verify(contract.getTakerPubKeyRing().getSignaturePubKey(),
dispute.getContractAsJson(),
takerContractSignature);
}
} catch (CryptoException e) {
throw new ValidationException(dispute, e.getMessage());
}
} catch (Throwable t) { } catch (Throwable t) {
throw new ValidationException(dispute, t.getMessage()); throw new ValidationException(dispute, t.getMessage());
} }

View file

@ -23,6 +23,7 @@ import com.google.common.base.CaseFormat;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
import haveno.common.config.Config; import haveno.common.config.Config;
import haveno.common.crypto.Hash; import haveno.common.crypto.Hash;
import haveno.common.crypto.KeyRing;
import haveno.common.crypto.PubKeyRing; import haveno.common.crypto.PubKeyRing;
import haveno.common.crypto.Sig; import haveno.common.crypto.Sig;
import haveno.common.util.Utilities; import haveno.common.util.Utilities;
@ -39,7 +40,7 @@ import java.text.DecimalFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.net.URI; import java.net.URI;
import java.security.PrivateKey;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
@ -236,6 +237,170 @@ public class HavenoUtils {
return feePerXmrAsDecimal.multiply(amountMultiplier).toBigInteger(); return feePerXmrAsDecimal.multiply(amountMultiplier).toBigInteger();
} }
// ------------------------ SIGNING AND VERIFYING -------------------------
public static byte[] sign(KeyRing keyRing, String message) {
return sign(keyRing.getSignatureKeyPair().getPrivate(), message);
}
public static byte[] sign(PrivateKey privateKey, String message) {
return sign(privateKey, message.getBytes(Charsets.UTF_8));
}
public static byte[] sign(PrivateKey privateKey, byte[] bytes) {
try {
return Sig.sign(privateKey, bytes);
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
public static void verifySignature(PubKeyRing pubKeyRing, String message, byte[] signature) {
verifySignature(pubKeyRing, message.getBytes(Charsets.UTF_8), signature);
}
public static void verifySignature(PubKeyRing pubKeyRing, byte[] bytes, byte[] signature) {
try {
Sig.verify(pubKeyRing.getSignaturePubKey(), bytes, signature);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static boolean isSignatureValid(PubKeyRing pubKeyRing, String message, byte[] signature) {
return isSignatureValid(pubKeyRing, message.getBytes(Charsets.UTF_8), signature);
}
public static boolean isSignatureValid(PubKeyRing pubKeyRing, byte[] bytes, byte[] signature) {
try {
verifySignature(pubKeyRing, bytes, signature);
return true;
} catch (Exception e) {
return false;
}
}
/**
* Check if the arbitrator signature is valid for an offer.
*
* @param offer is a signed offer with payload
* @param arbitrator is the original signing arbitrator
* @return true if the arbitrator's signature is valid for the offer
*/
public static boolean isArbitratorSignatureValid(Offer offer, Arbitrator arbitrator) {
// copy offer payload
OfferPayload offerPayloadCopy = OfferPayload.fromProto(offer.toProtoMessage().getOfferPayload());
// remove arbitrator signature from signed payload
byte[] signature = offerPayloadCopy.getArbitratorSignature();
offerPayloadCopy.setArbitratorSignature(null);
// get unsigned offer payload as json string
String unsignedOfferAsJson = JsonUtil.objectToJson(offerPayloadCopy);
// verify signature
return isSignatureValid(arbitrator.getPubKeyRing(), unsignedOfferAsJson, signature);
}
/**
* Check if the maker signature for a trade request is valid.
*
* @param request is the trade request to check
* @return true if the maker's signature is valid for the trade request
*/
public static boolean isMakerSignatureValid(InitTradeRequest request, byte[] signature, PubKeyRing makerPubKeyRing) {
// re-create trade request with signed fields
InitTradeRequest signedRequest = new InitTradeRequest(
request.getTradeId(),
request.getSenderNodeAddress(),
request.getPubKeyRing(),
request.getTradeAmount(),
request.getTradePrice(),
request.getTradeFee(),
request.getAccountId(),
request.getPaymentAccountId(),
request.getPaymentMethodId(),
request.getUid(),
request.getMessageVersion(),
request.getAccountAgeWitnessSignatureOfOfferId(),
request.getCurrentDate(),
request.getMakerNodeAddress(),
request.getTakerNodeAddress(),
null,
null,
null,
null,
request.getPayoutAddress(),
null
);
// get trade request as string
String tradeRequestAsJson = JsonUtil.objectToJson(signedRequest);
// verify maker signature
return isSignatureValid(makerPubKeyRing, tradeRequestAsJson, signature);
}
/**
* Verify the buyer signature for a PaymentSentMessage.
*
* @param trade - the trade to verify
* @param message - signed payment sent message to verify
* @return true if the buyer's signature is valid for the message
*/
public static void verifyPaymentSentMessage(Trade trade, PaymentSentMessage message) {
// remove signature from message
byte[] signature = message.getBuyerSignature();
message.setBuyerSignature(null);
// get unsigned message as json string
String unsignedMessageAsJson = JsonUtil.objectToJson(message);
// replace signature
message.setBuyerSignature(signature);
// verify signature
if (!isSignatureValid(trade.getBuyer().getPubKeyRing(), unsignedMessageAsJson, signature)) {
throw new IllegalArgumentException("The buyer signature is invalid for the " + message.getClass().getSimpleName() + " for " + trade.getClass().getSimpleName() + " " + trade.getId());
}
// verify trade id
if (!trade.getId().equals(message.getTradeId())) throw new IllegalArgumentException("The " + message.getClass().getSimpleName() + " has the wrong trade id, expected " + trade.getId() + " but was " + message.getTradeId());
}
/**
* Verify the seller signature for a PaymentReceivedMessage.
*
* @param trade - the trade to verify
* @param message - signed payment received message to verify
* @return true if the seller's signature is valid for the message
*/
public static void verifyPaymentReceivedMessage(Trade trade, PaymentReceivedMessage message) {
// remove signature from message
byte[] signature = message.getSellerSignature();
message.setSellerSignature(null);
// get unsigned message as json string
String unsignedMessageAsJson = JsonUtil.objectToJson(message);
// replace signature
message.setSellerSignature(signature);
// verify signature
if (!isSignatureValid(trade.getSeller().getPubKeyRing(), unsignedMessageAsJson, signature)) {
throw new IllegalArgumentException("The seller signature is invalid for the " + message.getClass().getSimpleName() + " for " + trade.getClass().getSimpleName() + " " + trade.getId());
}
// verify trade id
if (!trade.getId().equals(message.getTradeId())) throw new IllegalArgumentException("The " + message.getClass().getSimpleName() + " has the wrong trade id, expected " + trade.getId() + " but was " + message.getTradeId());
// verify buyer signature of payment sent message
verifyPaymentSentMessage(trade, message.getPaymentSentMessage());
}
// ----------------------------- OTHER UTILS ------------------------------ // ----------------------------- OTHER UTILS ------------------------------
@ -282,144 +447,6 @@ public class HavenoUtils {
return Utilities.bytesAsHexString(Hash.getSha256Ripemd160hash(uniqueId.getBytes(Charsets.UTF_8))); return Utilities.bytesAsHexString(Hash.getSha256Ripemd160hash(uniqueId.getBytes(Charsets.UTF_8)));
} }
/**
* Check if the arbitrator signature is valid for an offer.
*
* @param offer is a signed offer with payload
* @param arbitrator is the original signing arbitrator
* @return true if the arbitrator's signature is valid for the offer
*/
public static boolean isArbitratorSignatureValid(Offer offer, Arbitrator arbitrator) {
// copy offer payload
OfferPayload offerPayloadCopy = OfferPayload.fromProto(offer.toProtoMessage().getOfferPayload());
// remove arbitrator signature from signed payload
String signature = offerPayloadCopy.getArbitratorSignature();
offerPayloadCopy.setArbitratorSignature(null);
// get unsigned offer payload as json string
String unsignedOfferAsJson = JsonUtil.objectToJson(offerPayloadCopy);
// verify arbitrator signature
try {
return Sig.verify(arbitrator.getPubKeyRing().getSignaturePubKey(), unsignedOfferAsJson, signature);
} catch (Exception e) {
return false;
}
}
/**
* Check if the maker signature for a trade request is valid.
*
* @param request is the trade request to check
* @return true if the maker's signature is valid for the trade request
*/
public static boolean isMakerSignatureValid(InitTradeRequest request, String signature, PubKeyRing makerPubKeyRing) {
// re-create trade request with signed fields
InitTradeRequest signedRequest = new InitTradeRequest(
request.getTradeId(),
request.getSenderNodeAddress(),
request.getPubKeyRing(),
request.getTradeAmount(),
request.getTradePrice(),
request.getTradeFee(),
request.getAccountId(),
request.getPaymentAccountId(),
request.getPaymentMethodId(),
request.getUid(),
request.getMessageVersion(),
request.getAccountAgeWitnessSignatureOfOfferId(),
request.getCurrentDate(),
request.getMakerNodeAddress(),
request.getTakerNodeAddress(),
null,
null,
null,
null,
request.getPayoutAddress(),
null
);
// get trade request as string
String tradeRequestAsJson = JsonUtil.objectToJson(signedRequest);
// verify maker signature
try {
return Sig.verify(makerPubKeyRing.getSignaturePubKey(),
tradeRequestAsJson,
signature);
} catch (Exception e) {
return false;
}
}
/**
* Verify the buyer signature for a PaymentSentMessage.
*
* @param trade - the trade to verify
* @param message - signed payment sent message to verify
* @return true if the buyer's signature is valid for the message
*/
public static void verifyPaymentSentMessage(Trade trade, PaymentSentMessage message) {
// remove signature from message
byte[] signature = message.getBuyerSignature();
message.setBuyerSignature(null);
// get unsigned message as json string
String unsignedMessageAsJson = JsonUtil.objectToJson(message);
// replace signature
message.setBuyerSignature(signature);
// verify signature
String errMessage = "The buyer signature is invalid for the " + message.getClass().getSimpleName() + " for " + trade.getClass().getSimpleName() + " " + trade.getId();
try {
if (!Sig.verify(trade.getBuyer().getPubKeyRing().getSignaturePubKey(), unsignedMessageAsJson.getBytes(Charsets.UTF_8), signature)) throw new IllegalArgumentException(errMessage);
} catch (Exception e) {
throw new IllegalArgumentException(errMessage);
}
// verify trade id
if (!trade.getId().equals(message.getTradeId())) throw new IllegalArgumentException("The " + message.getClass().getSimpleName() + " has the wrong trade id, expected " + trade.getId() + " but was " + message.getTradeId());
}
/**
* Verify the seller signature for a PaymentReceivedMessage.
*
* @param trade - the trade to verify
* @param message - signed payment received message to verify
* @return true if the seller's signature is valid for the message
*/
public static void verifyPaymentReceivedMessage(Trade trade, PaymentReceivedMessage message) {
// remove signature from message
byte[] signature = message.getSellerSignature();
message.setSellerSignature(null);
// get unsigned message as json string
String unsignedMessageAsJson = JsonUtil.objectToJson(message);
// replace signature
message.setSellerSignature(signature);
// verify signature
String errMessage = "The seller signature is invalid for the " + message.getClass().getSimpleName() + " for " + trade.getClass().getSimpleName() + " " + trade.getId();
try {
if (!Sig.verify(trade.getSeller().getPubKeyRing().getSignaturePubKey(), unsignedMessageAsJson.getBytes(Charsets.UTF_8), signature)) throw new IllegalArgumentException(errMessage);
} catch (Exception e) {
throw new IllegalArgumentException(errMessage);
}
// verify trade id
if (!trade.getId().equals(message.getTradeId())) throw new IllegalArgumentException("The " + message.getClass().getSimpleName() + " has the wrong trade id, expected " + trade.getId() + " but was " + message.getTradeId());
// verify buyer signature of payment sent message
verifyPaymentSentMessage(trade, message.getPaymentSentMessage());
}
public static void awaitLatch(CountDownLatch latch) { public static void awaitLatch(CountDownLatch latch) {
try { try {
latch.await(); latch.await();

View file

@ -19,6 +19,7 @@ package haveno.core.trade.messages;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import haveno.common.proto.ProtoUtil; import haveno.common.proto.ProtoUtil;
import haveno.common.util.Utilities;
import haveno.core.proto.CoreProtoResolver; import haveno.core.proto.CoreProtoResolver;
import haveno.network.p2p.DirectMessage; import haveno.network.p2p.DirectMessage;
import java.util.Optional; import java.util.Optional;
@ -30,7 +31,7 @@ import lombok.Value;
@Value @Value
public final class DepositRequest extends TradeMessage implements DirectMessage { public final class DepositRequest extends TradeMessage implements DirectMessage {
private final long currentDate; private final long currentDate;
private final String contractSignature; private final byte[] contractSignature;
private final String depositTxHex; private final String depositTxHex;
private final String depositTxKey; private final String depositTxKey;
@Nullable @Nullable
@ -40,7 +41,7 @@ public final class DepositRequest extends TradeMessage implements DirectMessage
String uid, String uid,
String messageVersion, String messageVersion,
long currentDate, long currentDate,
String contractSignature, byte[] contractSignature,
String depositTxHex, String depositTxHex,
String depositTxKey, String depositTxKey,
@Nullable byte[] paymentAccountKey) { @Nullable byte[] paymentAccountKey) {
@ -62,11 +63,11 @@ public final class DepositRequest extends TradeMessage implements DirectMessage
protobuf.DepositRequest.Builder builder = protobuf.DepositRequest.newBuilder() protobuf.DepositRequest.Builder builder = protobuf.DepositRequest.newBuilder()
.setTradeId(tradeId) .setTradeId(tradeId)
.setUid(uid) .setUid(uid)
.setContractSignature(contractSignature)
.setDepositTxHex(depositTxHex) .setDepositTxHex(depositTxHex)
.setDepositTxKey(depositTxKey); .setDepositTxKey(depositTxKey);
builder.setCurrentDate(currentDate); builder.setCurrentDate(currentDate);
Optional.ofNullable(paymentAccountKey).ifPresent(e -> builder.setPaymentAccountKey(ByteString.copyFrom(e))); Optional.ofNullable(paymentAccountKey).ifPresent(e -> builder.setPaymentAccountKey(ByteString.copyFrom(e)));
Optional.ofNullable(contractSignature).ifPresent(e -> builder.setContractSignature(ByteString.copyFrom(e)));
return getNetworkEnvelopeBuilder().setDepositRequest(builder).build(); return getNetworkEnvelopeBuilder().setDepositRequest(builder).build();
} }
@ -78,7 +79,7 @@ public final class DepositRequest extends TradeMessage implements DirectMessage
proto.getUid(), proto.getUid(),
messageVersion, messageVersion,
proto.getCurrentDate(), proto.getCurrentDate(),
proto.getContractSignature(), ProtoUtil.byteArrayOrNullFromProto(proto.getContractSignature()),
proto.getDepositTxHex(), proto.getDepositTxHex(),
proto.getDepositTxKey(), proto.getDepositTxKey(),
ProtoUtil.byteArrayOrNullFromProto(proto.getPaymentAccountKey())); ProtoUtil.byteArrayOrNullFromProto(proto.getPaymentAccountKey()));
@ -88,7 +89,7 @@ public final class DepositRequest extends TradeMessage implements DirectMessage
public String toString() { public String toString() {
return "DepositRequest {" + return "DepositRequest {" +
",\n currentDate=" + currentDate + ",\n currentDate=" + currentDate +
",\n contractSignature=" + contractSignature + ",\n contractSignature=" + Utilities.bytesAsHexString(contractSignature) +
",\n depositTxHex='" + depositTxHex + ",\n depositTxHex='" + depositTxHex +
",\n depositTxKey='" + depositTxKey + ",\n depositTxKey='" + depositTxKey +
",\n paymentAccountKey='" + paymentAccountKey + ",\n paymentAccountKey='" + paymentAccountKey +

View file

@ -62,7 +62,7 @@ public final class InitTradeRequest extends TradeMessage implements DirectMessag
@Nullable @Nullable
private final String payoutAddress; private final String payoutAddress;
@Nullable @Nullable
private final String makerSignature; private final byte[] makerSignature;
public InitTradeRequest(String tradeId, public InitTradeRequest(String tradeId,
NodeAddress senderNodeAddress, NodeAddress senderNodeAddress,
@ -84,7 +84,7 @@ public final class InitTradeRequest extends TradeMessage implements DirectMessag
@Nullable String reserveTxHex, @Nullable String reserveTxHex,
@Nullable String reserveTxKey, @Nullable String reserveTxKey,
@Nullable String payoutAddress, @Nullable String payoutAddress,
@Nullable String makerSignature) { @Nullable byte[] makerSignature) {
super(messageVersion, tradeId, uid); super(messageVersion, tradeId, uid);
this.senderNodeAddress = senderNodeAddress; this.senderNodeAddress = senderNodeAddress;
this.pubKeyRing = pubKeyRing; this.pubKeyRing = pubKeyRing;
@ -133,7 +133,7 @@ public final class InitTradeRequest extends TradeMessage implements DirectMessag
Optional.ofNullable(reserveTxKey).ifPresent(e -> builder.setReserveTxKey(reserveTxKey)); Optional.ofNullable(reserveTxKey).ifPresent(e -> builder.setReserveTxKey(reserveTxKey));
Optional.ofNullable(payoutAddress).ifPresent(e -> builder.setPayoutAddress(payoutAddress)); Optional.ofNullable(payoutAddress).ifPresent(e -> builder.setPayoutAddress(payoutAddress));
Optional.ofNullable(accountAgeWitnessSignatureOfOfferId).ifPresent(e -> builder.setAccountAgeWitnessSignatureOfOfferId(ByteString.copyFrom(e))); Optional.ofNullable(accountAgeWitnessSignatureOfOfferId).ifPresent(e -> builder.setAccountAgeWitnessSignatureOfOfferId(ByteString.copyFrom(e)));
Optional.ofNullable(makerSignature).ifPresent(e -> builder.setMakerSignature(makerSignature)); Optional.ofNullable(makerSignature).ifPresent(e -> builder.setMakerSignature(ByteString.copyFrom(e)));
builder.setCurrentDate(currentDate); builder.setCurrentDate(currentDate);
return getNetworkEnvelopeBuilder().setInitTradeRequest(builder).build(); return getNetworkEnvelopeBuilder().setInitTradeRequest(builder).build();
@ -162,7 +162,7 @@ public final class InitTradeRequest extends TradeMessage implements DirectMessag
ProtoUtil.stringOrNullFromProto(proto.getReserveTxHex()), ProtoUtil.stringOrNullFromProto(proto.getReserveTxHex()),
ProtoUtil.stringOrNullFromProto(proto.getReserveTxKey()), ProtoUtil.stringOrNullFromProto(proto.getReserveTxKey()),
ProtoUtil.stringOrNullFromProto(proto.getPayoutAddress()), ProtoUtil.stringOrNullFromProto(proto.getPayoutAddress()),
ProtoUtil.stringOrNullFromProto(proto.getMakerSignature())); ProtoUtil.byteArrayOrNullFromProto(proto.getMakerSignature()));
} }
@Override @Override
@ -183,7 +183,7 @@ public final class InitTradeRequest extends TradeMessage implements DirectMessag
",\n reserveTxHex=" + reserveTxHex + ",\n reserveTxHex=" + reserveTxHex +
",\n reserveTxKey=" + reserveTxKey + ",\n reserveTxKey=" + reserveTxKey +
",\n payoutAddress=" + payoutAddress + ",\n payoutAddress=" + payoutAddress +
",\n makerSignature=" + makerSignature + ",\n makerSignature=" + Utilities.byteArrayToInteger(makerSignature) +
"\n} " + super.toString(); "\n} " + super.toString();
} }
} }

View file

@ -18,11 +18,10 @@
package haveno.core.trade.messages; package haveno.core.trade.messages;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import haveno.common.crypto.PubKeyRing;
import haveno.common.proto.ProtoUtil; import haveno.common.proto.ProtoUtil;
import haveno.common.util.Utilities;
import haveno.core.proto.CoreProtoResolver; import haveno.core.proto.CoreProtoResolver;
import haveno.network.p2p.DirectMessage; import haveno.network.p2p.DirectMessage;
import haveno.network.p2p.NodeAddress;
import java.util.Optional; import java.util.Optional;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
@ -33,7 +32,7 @@ import lombok.Value;
public final class SignContractResponse extends TradeMessage implements DirectMessage { public final class SignContractResponse extends TradeMessage implements DirectMessage {
private final long currentDate; private final long currentDate;
private final String contractAsJson; private final String contractAsJson;
private final String contractSignature; private final byte[] contractSignature;
private final byte[] encryptedPaymentAccountPayload; private final byte[] encryptedPaymentAccountPayload;
public SignContractResponse(String tradeId, public SignContractResponse(String tradeId,
@ -41,7 +40,7 @@ public final class SignContractResponse extends TradeMessage implements DirectMe
String messageVersion, String messageVersion,
long currentDate, long currentDate,
String contractAsJson, String contractAsJson,
String contractSignature, byte[] contractSignature,
@Nullable byte[] encryptedPaymentAccountPayload) { @Nullable byte[] encryptedPaymentAccountPayload) {
super(messageVersion, tradeId, uid); super(messageVersion, tradeId, uid);
this.currentDate = currentDate; this.currentDate = currentDate;
@ -62,7 +61,7 @@ public final class SignContractResponse extends TradeMessage implements DirectMe
.setUid(uid); .setUid(uid);
Optional.ofNullable(contractAsJson).ifPresent(e -> builder.setContractAsJson(contractAsJson)); Optional.ofNullable(contractAsJson).ifPresent(e -> builder.setContractAsJson(contractAsJson));
Optional.ofNullable(contractSignature).ifPresent(e -> builder.setContractSignature(contractSignature)); Optional.ofNullable(contractSignature).ifPresent(e -> builder.setContractSignature(ByteString.copyFrom(e)));
Optional.ofNullable(encryptedPaymentAccountPayload).ifPresent(e -> builder.setEncryptedPaymentAccountPayload(ByteString.copyFrom(e))); Optional.ofNullable(encryptedPaymentAccountPayload).ifPresent(e -> builder.setEncryptedPaymentAccountPayload(ByteString.copyFrom(e)));
builder.setCurrentDate(currentDate); builder.setCurrentDate(currentDate);
@ -78,7 +77,7 @@ public final class SignContractResponse extends TradeMessage implements DirectMe
messageVersion, messageVersion,
proto.getCurrentDate(), proto.getCurrentDate(),
ProtoUtil.stringOrNullFromProto(proto.getContractAsJson()), ProtoUtil.stringOrNullFromProto(proto.getContractAsJson()),
ProtoUtil.stringOrNullFromProto(proto.getContractSignature()), ProtoUtil.byteArrayOrNullFromProto(proto.getContractSignature()),
proto.getEncryptedPaymentAccountPayload().toByteArray()); proto.getEncryptedPaymentAccountPayload().toByteArray());
} }
@ -87,7 +86,7 @@ public final class SignContractResponse extends TradeMessage implements DirectMe
return "SignContractResponse {" + return "SignContractResponse {" +
",\n currentDate=" + currentDate + ",\n currentDate=" + currentDate +
",\n contractAsJson='" + contractAsJson + ",\n contractAsJson='" + contractAsJson +
",\n contractSignature='" + contractSignature + ",\n contractSignature='" + Utilities.bytesAsHexString(contractSignature) +
"\n} " + super.toString(); "\n} " + super.toString();
} }
} }

View file

@ -137,7 +137,7 @@ public class ProcessModel implements Model, PersistablePayload {
transient private TradeMessage tradeMessage; transient private TradeMessage tradeMessage;
@Getter @Getter
@Setter @Setter
private String makerSignature; private byte[] makerSignature;
@Nullable @Nullable
@Getter @Getter
@Setter @Setter
@ -220,7 +220,8 @@ public class ProcessModel implements Model, PersistablePayload {
Optional.ofNullable(takeOfferFeeTxId).ifPresent(builder::setTakeOfferFeeTxId); Optional.ofNullable(takeOfferFeeTxId).ifPresent(builder::setTakeOfferFeeTxId);
Optional.ofNullable(payoutTxSignature).ifPresent(e -> builder.setPayoutTxSignature(ByteString.copyFrom(payoutTxSignature))); Optional.ofNullable(payoutTxSignature).ifPresent(e -> builder.setPayoutTxSignature(ByteString.copyFrom(payoutTxSignature)));
Optional.ofNullable(tempTradePeerNodeAddress).ifPresent(e -> builder.setTempTradePeerNodeAddress(tempTradePeerNodeAddress.toProtoMessage())); Optional.ofNullable(tempTradePeerNodeAddress).ifPresent(e -> builder.setTempTradePeerNodeAddress(tempTradePeerNodeAddress.toProtoMessage()));
Optional.ofNullable(makerSignature).ifPresent(e -> builder.setMakerSignature(makerSignature)); Optional.ofNullable(mediatedPayoutTxSignature).ifPresent(e -> builder.setMediatedPayoutTxSignature(ByteString.copyFrom(e)));
Optional.ofNullable(makerSignature).ifPresent(e -> builder.setMakerSignature(ByteString.copyFrom(e)));
Optional.ofNullable(multisigAddress).ifPresent(e -> builder.setMultisigAddress(multisigAddress)); Optional.ofNullable(multisigAddress).ifPresent(e -> builder.setMultisigAddress(multisigAddress));
Optional.ofNullable(paymentSentMessage).ifPresent(e -> builder.setPaymentSentMessage(paymentSentMessage.toProtoNetworkEnvelope().getPaymentSentMessage())); Optional.ofNullable(paymentSentMessage).ifPresent(e -> builder.setPaymentSentMessage(paymentSentMessage.toProtoNetworkEnvelope().getPaymentSentMessage()));
Optional.ofNullable(paymentReceivedMessage).ifPresent(e -> builder.setPaymentReceivedMessage(paymentReceivedMessage.toProtoNetworkEnvelope().getPaymentReceivedMessage())); Optional.ofNullable(paymentReceivedMessage).ifPresent(e -> builder.setPaymentReceivedMessage(paymentReceivedMessage.toProtoNetworkEnvelope().getPaymentReceivedMessage()));
@ -245,7 +246,7 @@ public class ProcessModel implements Model, PersistablePayload {
processModel.setPayoutTxSignature(ProtoUtil.byteArrayOrNullFromProto(proto.getPayoutTxSignature())); processModel.setPayoutTxSignature(ProtoUtil.byteArrayOrNullFromProto(proto.getPayoutTxSignature()));
processModel.setTempTradePeerNodeAddress(proto.hasTempTradePeerNodeAddress() ? NodeAddress.fromProto(proto.getTempTradePeerNodeAddress()) : null); processModel.setTempTradePeerNodeAddress(proto.hasTempTradePeerNodeAddress() ? NodeAddress.fromProto(proto.getTempTradePeerNodeAddress()) : null);
processModel.setMediatedPayoutTxSignature(ProtoUtil.byteArrayOrNullFromProto(proto.getMediatedPayoutTxSignature())); processModel.setMediatedPayoutTxSignature(ProtoUtil.byteArrayOrNullFromProto(proto.getMediatedPayoutTxSignature()));
processModel.setMakerSignature(proto.getMakerSignature()); processModel.setMakerSignature(ProtoUtil.byteArrayOrNullFromProto(proto.getMakerSignature()));
processModel.setMultisigAddress(ProtoUtil.stringOrNullFromProto(proto.getMultisigAddress())); processModel.setMultisigAddress(ProtoUtil.stringOrNullFromProto(proto.getMultisigAddress()));
String paymentSentMessageStateString = ProtoUtil.stringOrNullFromProto(proto.getPaymentSentMessageState()); String paymentSentMessageStateString = ProtoUtil.stringOrNullFromProto(proto.getPaymentSentMessageState());

View file

@ -79,7 +79,7 @@ public final class TradePeer implements PersistablePayload {
@Nullable @Nullable
private String contractAsJson; private String contractAsJson;
@Nullable @Nullable
private String contractSignature; private byte[] contractSignature;
// added in v 0.6 // added in v 0.6
@Nullable @Nullable
@ -146,7 +146,7 @@ public final class TradePeer implements PersistablePayload {
Optional.ofNullable(paymentAccountPayload).ifPresent(e -> builder.setPaymentAccountPayload((protobuf.PaymentAccountPayload) e.toProtoMessage())); Optional.ofNullable(paymentAccountPayload).ifPresent(e -> builder.setPaymentAccountPayload((protobuf.PaymentAccountPayload) e.toProtoMessage()));
Optional.ofNullable(payoutAddressString).ifPresent(builder::setPayoutAddressString); Optional.ofNullable(payoutAddressString).ifPresent(builder::setPayoutAddressString);
Optional.ofNullable(contractAsJson).ifPresent(builder::setContractAsJson); Optional.ofNullable(contractAsJson).ifPresent(builder::setContractAsJson);
Optional.ofNullable(contractSignature).ifPresent(builder::setContractSignature); Optional.ofNullable(contractSignature).ifPresent(e -> builder.setContractSignature(ByteString.copyFrom(e)));
Optional.ofNullable(pubKeyRing).ifPresent(e -> builder.setPubKeyRing(e.toProtoMessage())); Optional.ofNullable(pubKeyRing).ifPresent(e -> builder.setPubKeyRing(e.toProtoMessage()));
Optional.ofNullable(accountAgeWitnessNonce).ifPresent(e -> builder.setAccountAgeWitnessNonce(ByteString.copyFrom(e))); Optional.ofNullable(accountAgeWitnessNonce).ifPresent(e -> builder.setAccountAgeWitnessNonce(ByteString.copyFrom(e)));
Optional.ofNullable(accountAgeWitnessSignature).ifPresent(e -> builder.setAccountAgeWitnessSignature(ByteString.copyFrom(e))); Optional.ofNullable(accountAgeWitnessSignature).ifPresent(e -> builder.setAccountAgeWitnessSignature(ByteString.copyFrom(e)));
@ -185,7 +185,7 @@ public final class TradePeer implements PersistablePayload {
tradePeer.setPaymentAccountPayload(proto.hasPaymentAccountPayload() ? coreProtoResolver.fromProto(proto.getPaymentAccountPayload()) : null); tradePeer.setPaymentAccountPayload(proto.hasPaymentAccountPayload() ? coreProtoResolver.fromProto(proto.getPaymentAccountPayload()) : null);
tradePeer.setPayoutAddressString(ProtoUtil.stringOrNullFromProto(proto.getPayoutAddressString())); tradePeer.setPayoutAddressString(ProtoUtil.stringOrNullFromProto(proto.getPayoutAddressString()));
tradePeer.setContractAsJson(ProtoUtil.stringOrNullFromProto(proto.getContractAsJson())); tradePeer.setContractAsJson(ProtoUtil.stringOrNullFromProto(proto.getContractAsJson()));
tradePeer.setContractSignature(ProtoUtil.stringOrNullFromProto(proto.getContractSignature())); tradePeer.setContractSignature(ProtoUtil.byteArrayOrNullFromProto(proto.getContractSignature()));
tradePeer.setPubKeyRing(proto.hasPubKeyRing() ? PubKeyRing.fromProto(proto.getPubKeyRing()) : null); tradePeer.setPubKeyRing(proto.hasPubKeyRing() ? PubKeyRing.fromProto(proto.getPubKeyRing()) : null);
tradePeer.setAccountAgeWitnessNonce(ProtoUtil.byteArrayOrNullFromProto(proto.getAccountAgeWitnessNonce())); tradePeer.setAccountAgeWitnessNonce(ProtoUtil.byteArrayOrNullFromProto(proto.getAccountAgeWitnessNonce()));
tradePeer.setAccountAgeWitnessSignature(ProtoUtil.byteArrayOrNullFromProto(proto.getAccountAgeWitnessSignature())); tradePeer.setAccountAgeWitnessSignature(ProtoUtil.byteArrayOrNullFromProto(proto.getAccountAgeWitnessSignature()));

View file

@ -24,6 +24,7 @@ import haveno.common.crypto.PubKeyRing;
import haveno.common.crypto.Sig; import haveno.common.crypto.Sig;
import haveno.common.taskrunner.TaskRunner; import haveno.common.taskrunner.TaskRunner;
import haveno.core.offer.Offer; import haveno.core.offer.Offer;
import haveno.core.trade.HavenoUtils;
import haveno.core.trade.Trade; import haveno.core.trade.Trade;
import haveno.core.trade.messages.DepositRequest; import haveno.core.trade.messages.DepositRequest;
import haveno.core.trade.messages.DepositResponse; import haveno.core.trade.messages.DepositResponse;
@ -58,7 +59,7 @@ public class ArbitratorProcessDepositRequest extends TradeTask {
// get contract and signature // get contract and signature
String contractAsJson = trade.getContractAsJson(); String contractAsJson = trade.getContractAsJson();
DepositRequest request = (DepositRequest) processModel.getTradeMessage(); // TODO (woodser): verify response DepositRequest request = (DepositRequest) processModel.getTradeMessage(); // TODO (woodser): verify response
String signature = request.getContractSignature(); byte[] signature = request.getContractSignature();
// get trader info // get trader info
TradePeer trader = trade.getTradePeer(processModel.getTempTradePeerNodeAddress()); TradePeer trader = trade.getTradePeer(processModel.getTempTradePeerNodeAddress());
@ -66,7 +67,9 @@ public class ArbitratorProcessDepositRequest extends TradeTask {
PubKeyRing peerPubKeyRing = trader.getPubKeyRing(); PubKeyRing peerPubKeyRing = trader.getPubKeyRing();
// verify signature // verify signature
if (!Sig.verify(peerPubKeyRing.getSignaturePubKey(), contractAsJson, signature)) throw new RuntimeException("Peer's contract signature is invalid"); if (!HavenoUtils.isSignatureValid(peerPubKeyRing, contractAsJson, signature)) {
throw new RuntimeException("Peer's contract signature is invalid");
}
// set peer's signature // set peer's signature
trader.setContractSignature(signature); trader.setContractSignature(signature);

View file

@ -17,10 +17,8 @@
package haveno.core.trade.protocol.tasks; package haveno.core.trade.protocol.tasks;
import com.google.common.base.Charsets;
import haveno.common.Timer; import haveno.common.Timer;
import haveno.common.crypto.PubKeyRing; import haveno.common.crypto.PubKeyRing;
import haveno.common.crypto.Sig;
import haveno.common.taskrunner.TaskRunner; import haveno.common.taskrunner.TaskRunner;
import haveno.core.network.MessageState; import haveno.core.network.MessageState;
import haveno.core.trade.HavenoUtils; import haveno.core.trade.HavenoUtils;
@ -94,7 +92,7 @@ public abstract class BuyerSendPaymentSentMessage extends SendMailboxMessageTask
// sign message // sign message
try { try {
String messageAsJson = JsonUtil.objectToJson(message); String messageAsJson = JsonUtil.objectToJson(message);
byte[] sig = Sig.sign(processModel.getP2PService().getKeyRing().getSignatureKeyPair().getPrivate(), messageAsJson.getBytes(Charsets.UTF_8)); byte[] sig = HavenoUtils.sign(processModel.getP2PService().getKeyRing(), messageAsJson);
message.setBuyerSignature(sig); message.setBuyerSignature(sig);
processModel.setPaymentSentMessage(message); processModel.setPaymentSentMessage(message);
trade.requestPersistence(); trade.requestPersistence();

View file

@ -22,11 +22,10 @@ import java.util.Date;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import com.google.common.base.Charsets;
import haveno.common.app.Version; import haveno.common.app.Version;
import haveno.common.crypto.Sig;
import haveno.common.taskrunner.TaskRunner; import haveno.common.taskrunner.TaskRunner;
import haveno.core.trade.ArbitratorTrade; import haveno.core.trade.ArbitratorTrade;
import haveno.core.trade.HavenoUtils;
import haveno.core.trade.MakerTrade; import haveno.core.trade.MakerTrade;
import haveno.core.trade.Trade; import haveno.core.trade.Trade;
import haveno.core.trade.Trade.State; import haveno.core.trade.Trade.State;
@ -90,7 +89,7 @@ public class MaybeSendSignContractRequest extends TradeTask {
// maker signs deposit hash nonce to avoid challenge protocol // maker signs deposit hash nonce to avoid challenge protocol
byte[] sig = null; byte[] sig = null;
if (trade instanceof MakerTrade) { if (trade instanceof MakerTrade) {
sig = Sig.sign(processModel.getP2PService().getKeyRing().getSignatureKeyPair().getPrivate(), depositTx.getHash().getBytes(Charsets.UTF_8)); sig = HavenoUtils.sign(processModel.getP2PService().getKeyRing(), depositTx.getHash());
} }
// create request for peer and arbitrator to sign contract // create request for peer and arbitrator to sign contract

View file

@ -30,10 +30,10 @@ import haveno.common.crypto.Encryption;
import haveno.common.crypto.Hash; import haveno.common.crypto.Hash;
import haveno.common.crypto.PubKeyRing; import haveno.common.crypto.PubKeyRing;
import haveno.common.crypto.ScryptUtil; import haveno.common.crypto.ScryptUtil;
import haveno.common.crypto.Sig;
import haveno.common.taskrunner.TaskRunner; import haveno.common.taskrunner.TaskRunner;
import haveno.core.trade.ArbitratorTrade; import haveno.core.trade.ArbitratorTrade;
import haveno.core.trade.Contract; import haveno.core.trade.Contract;
import haveno.core.trade.HavenoUtils;
import haveno.core.trade.Trade; import haveno.core.trade.Trade;
import haveno.core.trade.Trade.State; import haveno.core.trade.Trade.State;
import haveno.core.trade.messages.SignContractRequest; import haveno.core.trade.messages.SignContractRequest;
@ -85,7 +85,7 @@ public class ProcessSignContractRequest extends TradeTask {
// create and sign contract // create and sign contract
Contract contract = trade.createContract(); Contract contract = trade.createContract();
String contractAsJson = JsonUtil.objectToJson(contract); String contractAsJson = JsonUtil.objectToJson(contract);
String signature = Sig.sign(processModel.getKeyRing().getSignatureKeyPair().getPrivate(), contractAsJson); byte[] signature = HavenoUtils.sign(processModel.getKeyRing(), contractAsJson);
// save contract and signature // save contract and signature
trade.setContract(contract); trade.setContract(contract);

View file

@ -20,8 +20,8 @@ package haveno.core.trade.protocol.tasks;
import haveno.common.app.Version; import haveno.common.app.Version;
import haveno.common.crypto.PubKeyRing; import haveno.common.crypto.PubKeyRing;
import haveno.common.crypto.Sig;
import haveno.common.taskrunner.TaskRunner; import haveno.common.taskrunner.TaskRunner;
import haveno.core.trade.HavenoUtils;
import haveno.core.trade.Trade; import haveno.core.trade.Trade;
import haveno.core.trade.messages.DepositRequest; import haveno.core.trade.messages.DepositRequest;
import haveno.core.trade.messages.SignContractResponse; import haveno.core.trade.messages.SignContractResponse;
@ -63,8 +63,8 @@ public class ProcessSignContractResponse extends TradeTask {
// verify signature // verify signature
// TODO (woodser): transfer contract for convenient comparison? // TODO (woodser): transfer contract for convenient comparison?
String signature = response.getContractSignature(); byte[] signature = response.getContractSignature();
if (!Sig.verify(peerPubKeyRing.getSignaturePubKey(), contractAsJson, signature)) throw new RuntimeException("Peer's contract signature is invalid"); if (!HavenoUtils.isSignatureValid(peerPubKeyRing, contractAsJson, signature)) throw new RuntimeException("Peer's contract signature is invalid");
// set peer's signature // set peer's signature
peer.setContractSignature(signature); peer.setContractSignature(signature);

View file

@ -22,9 +22,7 @@ import lombok.extern.slf4j.Slf4j;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Charsets;
import haveno.common.crypto.PubKeyRing; import haveno.common.crypto.PubKeyRing;
import haveno.common.crypto.Sig;
import haveno.common.taskrunner.TaskRunner; import haveno.common.taskrunner.TaskRunner;
import haveno.core.account.sign.SignedWitness; import haveno.core.account.sign.SignedWitness;
import haveno.core.account.witness.AccountAgeWitnessService; import haveno.core.account.witness.AccountAgeWitnessService;
@ -92,7 +90,7 @@ public abstract class SellerSendPaymentReceivedMessage extends SendMailboxMessag
// sign message // sign message
try { try {
String messageAsJson = JsonUtil.objectToJson(message); String messageAsJson = JsonUtil.objectToJson(message);
byte[] sig = Sig.sign(processModel.getP2PService().getKeyRing().getSignatureKeyPair().getPrivate(), messageAsJson.getBytes(Charsets.UTF_8)); byte[] sig = HavenoUtils.sign(processModel.getP2PService().getKeyRing(), messageAsJson);
message.setSellerSignature(sig); message.setSellerSignature(sig);
processModel.setPaymentReceivedMessage(message); processModel.setPaymentReceivedMessage(message);
trade.requestPersistence(); trade.requestPersistence();

View file

@ -18,6 +18,7 @@
package haveno.desktop.main.support.dispute.agent; package haveno.desktop.main.support.dispute.agent;
import haveno.common.UserThread; import haveno.common.UserThread;
import haveno.common.util.Utilities;
import haveno.core.locale.Res; import haveno.core.locale.Res;
import haveno.core.offer.OpenOfferManager; import haveno.core.offer.OpenOfferManager;
import haveno.core.offer.SignedOffer; import haveno.core.offer.SignedOffer;
@ -379,7 +380,7 @@ public class SignedOfferView extends ActivatableView<VBox, Void> {
public void updateItem(final SignedOffer item, boolean empty) { public void updateItem(final SignedOffer item, boolean empty) {
super.updateItem(item, empty); super.updateItem(item, empty);
if (item != null && !empty) if (item != null && !empty)
setText(item.getArbitratorSignature()); setText(Utilities.bytesAsHexString(item.getArbitratorSignature()));
else else
setText(""); setText("");
} }

View file

@ -165,7 +165,7 @@ message OfferAvailabilityResponse {
AvailabilityResult availability_result = 2; AvailabilityResult availability_result = 2;
repeated int32 supported_capabilities = 3; repeated int32 supported_capabilities = 3;
string uid = 4; string uid = 4;
string maker_signature = 5; bytes maker_signature = 5;
} }
message RefreshOfferMessage { message RefreshOfferMessage {
@ -233,7 +233,7 @@ message InitTradeRequest {
string reserve_tx_hex = 17; string reserve_tx_hex = 17;
string reserve_tx_key = 18; string reserve_tx_key = 18;
string payout_address = 19; string payout_address = 19;
string maker_signature = 20; bytes maker_signature = 20;
} }
message InitMultisigRequest { message InitMultisigRequest {
@ -261,7 +261,7 @@ message SignContractResponse {
string uid = 2; string uid = 2;
int64 current_date = 3; int64 current_date = 3;
string contract_as_json = 4; string contract_as_json = 4;
string contract_signature = 5; bytes contract_signature = 5;
bytes encrypted_payment_account_payload = 6; bytes encrypted_payment_account_payload = 6;
} }
@ -269,7 +269,7 @@ message DepositRequest {
string trade_id = 1; string trade_id = 1;
string uid = 2; string uid = 2;
int64 current_date = 3; int64 current_date = 3;
string contract_signature = 4; bytes contract_signature = 4;
string deposit_tx_hex = 5; string deposit_tx_hex = 5;
string deposit_tx_key = 6; string deposit_tx_key = 6;
bytes payment_account_key = 7; bytes payment_account_key = 7;
@ -636,7 +636,7 @@ message OfferPayload {
int32 protocol_version = 34; int32 protocol_version = 34;
NodeAddress arbitrator_signer = 1001; NodeAddress arbitrator_signer = 1001;
string arbitrator_signature = 1002; bytes arbitrator_signature = 1002;
repeated string reserve_tx_key_images = 1003; repeated string reserve_tx_key_images = 1003;
} }
@ -696,8 +696,8 @@ message Dispute {
string deposit_tx_id = 14; string deposit_tx_id = 14;
string payout_tx_id = 15; string payout_tx_id = 15;
string contract_as_json = 16; string contract_as_json = 16;
string maker_contract_signature = 17; bytes maker_contract_signature = 17;
string taker_contract_signature = 18; bytes taker_contract_signature = 18;
PaymentAccountPayload maker_payment_account_payload = 19; PaymentAccountPayload maker_payment_account_payload = 19;
PaymentAccountPayload taker_payment_account_payload = 20; PaymentAccountPayload taker_payment_account_payload = 20;
PubKeyRing agent_pub_key_ring = 21; PubKeyRing agent_pub_key_ring = 21;
@ -1356,7 +1356,7 @@ message SignedOffer {
string reserve_tx_hex = 7; string reserve_tx_hex = 7;
repeated string reserve_tx_key_images = 8; repeated string reserve_tx_key_images = 8;
uint64 reserve_tx_miner_fee = 9; uint64 reserve_tx_miner_fee = 9;
string arbitrator_signature = 10; bytes arbitrator_signature = 10;
} }
message OpenOffer { message OpenOffer {
@ -1531,7 +1531,7 @@ message ProcessModel {
int64 funds_needed_for_trade = 7; int64 funds_needed_for_trade = 7;
string payment_sent_message_state = 8; string payment_sent_message_state = 8;
bool deposits_confirmed_messages_delivered = 9; bool deposits_confirmed_messages_delivered = 9;
string maker_signature = 10; bytes maker_signature = 10;
TradePeer maker = 11; TradePeer maker = 11;
TradePeer taker = 12; TradePeer taker = 12;
TradePeer arbitrator = 13; TradePeer arbitrator = 13;
@ -1557,7 +1557,7 @@ message TradePeer {
PaymentAccountPayload payment_account_payload = 9; PaymentAccountPayload payment_account_payload = 9;
string payout_address_string = 10; string payout_address_string = 10;
string contract_as_json = 11; string contract_as_json = 11;
string contract_signature = 12; bytes contract_signature = 12;
bytes account_age_witness_nonce = 18; bytes account_age_witness_nonce = 18;
bytes account_age_witness_signature = 19; bytes account_age_witness_signature = 19;
AccountAgeWitness account_age_witness = 20; AccountAgeWitness account_age_witness = 20;