private void loadNextBlock() { while (true) { try { if (!fileIt.hasNext() && (currentFileStream == null || currentFileStream.available() < 1)) break; } catch (IOException e) { currentFileStream = null; if (!fileIt.hasNext()) break; } while (true) { try { if (currentFileStream != null && currentFileStream.available() > 0) break; } catch (IOException e1) { currentFileStream = null; } if (!fileIt.hasNext()) { nextBlock = null; currentFileStream = null; return; } try { currentFileStream = new FileInputStream(fileIt.next()); } catch (FileNotFoundException e) { currentFileStream = null; } } try { int nextChar = currentFileStream.read(); while (nextChar != -1) { if (nextChar != ((params.getPacketMagic() >>> 24) & 0xff)) { nextChar = currentFileStream.read(); continue; } nextChar = currentFileStream.read(); if (nextChar != ((params.getPacketMagic() >>> 16) & 0xff)) continue; nextChar = currentFileStream.read(); if (nextChar != ((params.getPacketMagic() >>> 8) & 0xff)) continue; nextChar = currentFileStream.read(); if (nextChar == (params.getPacketMagic() & 0xff)) break; } byte[] bytes = new byte[4]; currentFileStream.read(bytes, 0, 4); long size = Utils.readUint32BE(Utils.reverseBytes(bytes), 0); // We allow larger than MAX_BLOCK_SIZE because test code uses this as well. if (size > Block.MAX_BLOCK_SIZE * 2 || size <= 0) continue; bytes = new byte[(int) size]; currentFileStream.read(bytes, 0, (int) size); try { nextBlock = new Block(params, bytes); } catch (ProtocolException e) { nextBlock = null; continue; } break; } catch (IOException e) { currentFileStream = null; continue; } } }
public class PaymentSessionTest { private static final NetworkParameters params = TestNet3Params.get(); private static final String simplePaymentUrl = "http://a.simple.url.com/"; private static final String paymentRequestMemo = "send coinz noa plz kthx"; private static final String paymentMemo = "take ze coinz"; private static final ByteString merchantData = ByteString.copyFromUtf8("merchant data"); private static final long time = System.currentTimeMillis() / 1000L; private ECKey serverKey; private Transaction tx; private TransactionOutput outputToMe; BigInteger nanoCoins = Utils.toNanoCoins(1, 0); @Before public void setUp() throws Exception { serverKey = new ECKey(); tx = new Transaction(params); outputToMe = new TransactionOutput(params, tx, nanoCoins, serverKey); tx.addOutput(outputToMe); } @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()); assertEquals(paymentRequestMemo, paymentSession.getMemo()); assertEquals(nanoCoins, paymentSession.getValue()); assertEquals(simplePaymentUrl, paymentSession.getPaymentUrl()); assertTrue(new Date(time * 1000L).equals(paymentSession.getDate())); assertTrue(paymentSession.getSendRequest().tx.equals(tx)); assertFalse(paymentSession.isExpired()); // 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()); assertEquals(simplePaymentUrl, paymentSession.getPaymentLog().get(0).getUrl().toString()); Protos.Payment payment = paymentSession.getPaymentLog().get(0).getPayment(); assertEquals(paymentMemo, payment.getMemo()); assertEquals(merchantData, payment.getMerchantData()); assertEquals(1, payment.getRefundToCount()); assertEquals(nanoCoins.longValue(), payment.getRefundTo(0).getAmount()); TransactionOutput refundOutput = new TransactionOutput(params, null, nanoCoins, refundAddr); ByteString refundScript = ByteString.copyFrom(refundOutput.getScriptBytes()); assertTrue(refundScript.equals(payment.getRefundTo(0).getScript())); } @Test public void testDefaults() throws Exception { Protos.Output.Builder outputBuilder = Protos.Output.newBuilder().setScript(ByteString.copyFrom(outputToMe.getScriptBytes())); Protos.PaymentDetails paymentDetails = Protos.PaymentDetails.newBuilder().setTime(time).addOutputs(outputBuilder).build(); Protos.PaymentRequest paymentRequest = Protos.PaymentRequest.newBuilder() .setSerializedPaymentDetails(paymentDetails.toByteString()) .build(); MockPaymentSession paymentSession = new MockPaymentSession(paymentRequest); assertEquals(BigInteger.ZERO, paymentSession.getValue()); assertNull(paymentSession.getPaymentUrl()); assertNull(paymentSession.getMemo()); } @Test public void testExpiredPaymentRequest() throws Exception { MockPaymentSession paymentSession = new MockPaymentSession(newExpiredPaymentRequest()); assertTrue(paymentSession.isExpired()); // Send the payment and verify that an exception is thrown. // 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); try { paymentSession.sendPayment(txns, null, null); } catch (PaymentRequestException.Expired e) { assertEquals(0, paymentSession.getPaymentLog().size()); assertEquals(e.getMessage(), "PaymentRequest is expired"); return; } fail("Expected exception due to expired PaymentRequest"); } @Test public void testPkiVerification() throws Exception { InputStream in = getClass().getResourceAsStream("pki_test.bitcoinpaymentrequest"); Protos.PaymentRequest paymentRequest = Protos.PaymentRequest.newBuilder().mergeFrom(in).build(); MockPaymentSession paymentSession = new MockPaymentSession(paymentRequest); PaymentSession.PkiVerificationData pkiData = paymentSession.verifyPki(); assertEquals("www.bitcoincore.org", pkiData.name); assertEquals("The USERTRUST Network, Salt Lake City, US", pkiData.rootAuthorityName); } private Protos.PaymentRequest newSimplePaymentRequest() { Protos.Output.Builder outputBuilder = Protos.Output.newBuilder() .setAmount(nanoCoins.longValue()) .setScript(ByteString.copyFrom(outputToMe.getScriptBytes())); Protos.PaymentDetails paymentDetails = Protos.PaymentDetails.newBuilder() .setNetwork("test") .setTime(time) .setPaymentUrl(simplePaymentUrl) .addOutputs(outputBuilder) .setMemo(paymentRequestMemo) .setMerchantData(merchantData) .build(); Protos.PaymentRequest paymentRequest = Protos.PaymentRequest.newBuilder() .setPaymentDetailsVersion(1) .setPkiType("none") .setSerializedPaymentDetails(paymentDetails.toByteString()) .build(); return paymentRequest; } private Protos.PaymentRequest newExpiredPaymentRequest() { Protos.Output.Builder outputBuilder = Protos.Output.newBuilder() .setAmount(nanoCoins.longValue()) .setScript(ByteString.copyFrom(outputToMe.getScriptBytes())); Protos.PaymentDetails paymentDetails = Protos.PaymentDetails.newBuilder() .setNetwork("test") .setTime(time - 10) .setExpires(time - 1) .setPaymentUrl(simplePaymentUrl) .addOutputs(outputBuilder) .setMemo(paymentRequestMemo) .setMerchantData(merchantData) .build(); Protos.PaymentRequest paymentRequest = Protos.PaymentRequest.newBuilder() .setPaymentDetailsVersion(1) .setPkiType("none") .setSerializedPaymentDetails(paymentDetails.toByteString()) .build(); return paymentRequest; } private class MockPaymentSession extends PaymentSession { private ArrayList<PaymentLogItem> paymentLog = new ArrayList<PaymentLogItem>(); public MockPaymentSession(Protos.PaymentRequest request) throws PaymentRequestException { super(request); } public ArrayList<PaymentLogItem> getPaymentLog() { return paymentLog; } protected ListenableFuture<Ack> sendPayment(final URL url, final Protos.Payment payment) { paymentLog.add(new PaymentLogItem(url, payment)); return null; } public class PaymentLogItem { private final URL url; private final Protos.Payment payment; PaymentLogItem(final URL url, final Protos.Payment payment) { this.url = url; this.payment = payment; } public URL getUrl() { return url; } public Protos.Payment getPayment() { return payment; } } } }