Skip to content

Commit

Permalink
PaymentSession: Expose params and throw if transactions don't match r…
Browse files Browse the repository at this point in the history
…equested params.

Resolves issue 551.
  • Loading branch information
mikehearn committed Apr 30, 2014
1 parent 6160a2d commit c8ffc1e
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -323,9 +323,11 @@ public Wallet.SendRequest getSendRequest() {
* @param memo is a message to include in the payment message sent to the merchant.
*/
public @Nullable Protos.Payment getPayment(List<Transaction> txns, @Nullable Address refundAddr, @Nullable String memo)
throws IOException {
throws IOException, PaymentRequestException.InvalidNetwork {
if (!paymentDetails.hasPaymentUrl())
return null;
if (!txns.get(0).getParams().equals(params))
throw new PaymentRequestException.InvalidNetwork(params.getPaymentProtocolId());

This comment has been minimized.

Copy link
@mackuba

mackuba Apr 30, 2014

Is it possible to check this already in parsePaymentRequest? Or is this because there could be theoretically multiple Wallet instances connected to different networks, and you won't know before the user tries to send it?

This comment has been minimized.

Copy link
@mikehearn

mikehearn Apr 30, 2014

Author Member

I didn't want to change the API, so it could be backported to 0.11.3 for example. Yes it'd be possible, but you'd have to pass in networkparams. After parse but before payment you can just do

if (!session.getNetworkParams().equals(myParams)) { ... }

If you want something that works with the current code I think you can just get the proto directly and use NetworkParameters.fromPmtProtocolID(paymentDetails.getNetwork())

This comment has been minimized.

Copy link
@mackuba

mackuba Apr 30, 2014

Ah, ok, I didn't know PaymentSession has a getNetworkParams method on master (it doesn't in 0.11.2 - can you backport that too?). So that should be good enough. As a workaround I'm doing it like you said, by running that code from parsePaymentRequest myself to get the params and then comparing them to the ones in the wallet.

Protos.Payment.Builder payment = Protos.Payment.newBuilder();
if (paymentDetails.hasMerchantData())
payment.setMerchantData(paymentDetails.getMerchantData());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import com.google.bitcoin.core.*;
import com.google.bitcoin.crypto.TrustStoreLoader;
import com.google.bitcoin.params.MainNetParams;
import com.google.bitcoin.params.TestNet3Params;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.protobuf.ByteString;
Expand Down Expand Up @@ -57,7 +58,7 @@ public void setUp() throws Exception {
@Test
public void testSimplePayment() throws Exception {
// Create a PaymentRequest and make sure the correct values are parsed by the PaymentSession.
MockPaymentSession paymentSession = new MockPaymentSession(newSimplePaymentRequest());
MockPaymentSession paymentSession = new MockPaymentSession(newSimplePaymentRequest("test"));
assertEquals(paymentRequestMemo, paymentSession.getMemo());
assertEquals(nanoCoins, paymentSession.getValue());
assertEquals(simplePaymentUrl, paymentSession.getPaymentUrl());
Expand Down Expand Up @@ -130,24 +131,39 @@ public void testPkiVerification() throws Exception {
assertEquals("The USERTRUST Network, Salt Lake City, US", pkiData.rootAuthorityName);
}

private Protos.PaymentRequest newSimplePaymentRequest() {
@Test(expected = PaymentRequestException.InvalidNetwork.class)
public void testWrongNetwork() throws Exception {
// Create a PaymentRequest and make sure the correct values are parsed by the PaymentSession.
MockPaymentSession paymentSession = new MockPaymentSession(newSimplePaymentRequest("main"));
assertEquals(MainNetParams.get(), paymentSession.getNetworkParameters());

// Send the payment and verify that the correct information is sent.
// Add a dummy input to tx so it is considered valid.
tx.addInput(new TransactionInput(params, tx, outputToMe.getScriptBytes()));
ArrayList<Transaction> txns = new ArrayList<Transaction>();
txns.add(tx);
Address refundAddr = new Address(params, serverKey.getPubKeyHash());
paymentSession.sendPayment(txns, refundAddr, paymentMemo);
assertEquals(1, paymentSession.getPaymentLog().size());
}

private Protos.PaymentRequest newSimplePaymentRequest(String netID) {
Protos.Output.Builder outputBuilder = Protos.Output.newBuilder()
.setAmount(nanoCoins.longValue())
.setScript(ByteString.copyFrom(outputToMe.getScriptBytes()));
Protos.PaymentDetails paymentDetails = Protos.PaymentDetails.newBuilder()
.setNetwork("test")
.setNetwork(netID)
.setTime(time)
.setPaymentUrl(simplePaymentUrl)
.addOutputs(outputBuilder)
.setMemo(paymentRequestMemo)
.setMerchantData(merchantData)
.build();
Protos.PaymentRequest paymentRequest = Protos.PaymentRequest.newBuilder()
return Protos.PaymentRequest.newBuilder()
.setPaymentDetailsVersion(1)
.setPkiType("none")
.setSerializedPaymentDetails(paymentDetails.toByteString())
.build();
return paymentRequest;
}

private Protos.PaymentRequest newExpiredPaymentRequest() {
Expand All @@ -163,12 +179,11 @@ private Protos.PaymentRequest newExpiredPaymentRequest() {
.setMemo(paymentRequestMemo)
.setMerchantData(merchantData)
.build();
Protos.PaymentRequest paymentRequest = Protos.PaymentRequest.newBuilder()
return Protos.PaymentRequest.newBuilder()
.setPaymentDetailsVersion(1)
.setPkiType("none")
.setSerializedPaymentDetails(paymentDetails.toByteString())
.build();
return paymentRequest ;
}

private class MockPaymentSession extends PaymentSession {
Expand Down

0 comments on commit c8ffc1e

Please sign in to comment.