示例#1
0
 @Test
 public void exceptionListener() throws Exception {
   wallet.addEventListener(
       new AbstractWalletEventListener() {
         @Override
         public void onCoinsReceived(
             Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) {
           throw new NullPointerException("boo!");
         }
       });
   final Throwable[] throwables = new Throwable[1];
   Threading.uncaughtExceptionHandler =
       new Thread.UncaughtExceptionHandler() {
         @Override
         public void uncaughtException(Thread thread, Throwable throwable) {
           throwables[0] = throwable;
         }
       };
   // In real usage we're not really meant to adjust the uncaught exception handler after stuff
   // started happening
   // but in the unit test environment other tests have just run so the thread is probably still
   // kicking around.
   // Force it to crash so it'll be recreated with our new handler.
   Threading.USER_THREAD.execute(
       new Runnable() {
         @Override
         public void run() {
           throw new RuntimeException();
         }
       });
   connect();
   Transaction t1 = new Transaction(unitTestParams);
   t1.addInput(new TransactionInput(unitTestParams, t1, new byte[] {}));
   t1.addOutput(Utils.toNanoCoins(1, 0), new ECKey().toAddress(unitTestParams));
   Transaction t2 = new Transaction(unitTestParams);
   t2.addInput(t1.getOutput(0));
   t2.addOutput(Utils.toNanoCoins(1, 0), wallet.getChangeAddress());
   inbound(writeTarget, t2);
   final InventoryItem inventoryItem =
       new InventoryItem(InventoryItem.Type.Transaction, t2.getInput(0).getOutpoint().getHash());
   final NotFoundMessage nfm =
       new NotFoundMessage(unitTestParams, Lists.newArrayList(inventoryItem));
   inbound(writeTarget, nfm);
   pingAndWait(writeTarget);
   Threading.waitForUserCode();
   assertTrue(throwables[0] instanceof NullPointerException);
   Threading.uncaughtExceptionHandler = null;
 }
示例#2
0
  @Test
  public void getLargeBlock() throws Exception {
    connect();

    Block b1 = createFakeBlock(blockStore).block;
    blockChain.add(b1);
    Block b2 = makeSolvedTestBlock(b1);
    Transaction t = new Transaction(unitTestParams);
    t.addInput(b1.getTransactions().get(0).getOutput(0));
    t.addOutput(
        new TransactionOutput(
            unitTestParams, t, BigInteger.ZERO, new byte[Block.MAX_BLOCK_SIZE - 1000]));
    b2.addTransaction(t);

    // Request the block.
    Future<Block> resultFuture = peer.getBlock(b2.getHash());
    assertFalse(resultFuture.isDone());
    // Peer asks for it.
    GetDataMessage message = (GetDataMessage) outbound(writeTarget);
    assertEquals(message.getItems().get(0).hash, b2.getHash());
    assertFalse(resultFuture.isDone());
    // Peer receives it.
    inbound(writeTarget, b2);
    Block b = resultFuture.get();
    assertEquals(b, b2);
  }
  @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()));
  }
示例#4
0
  @Test
  public void testCreateMultiSigInputScript() throws AddressFormatException {
    // Setup transaction and signatures
    ECKey key1 =
        new DumpedPrivateKey(params, "cVLwRLTvz3BxDAWkvS3yzT9pUcTCup7kQnfT2smRjvmmm1wAP6QT")
            .getKey();
    ECKey key2 =
        new DumpedPrivateKey(params, "cTine92s8GLpVqvebi8rYce3FrUYq78ZGQffBYCS1HmDPJdSTxUo")
            .getKey();
    ECKey key3 =
        new DumpedPrivateKey(params, "cVHwXSPRZmL9adctwBwmn4oTZdZMbaCsR5XF6VznqMgcvt1FDDxg")
            .getKey();
    Script multisigScript =
        ScriptBuilder.createMultiSigOutputScript(2, Arrays.asList(key1, key2, key3));
    byte[] bytes =
        Hex.decode(
            "01000000013df681ff83b43b6585fa32dd0e12b0b502e6481e04ee52ff0fdaf55a16a4ef61000000006b483045022100a84acca7906c13c5895a1314c165d33621cdcf8696145080895cbf301119b7cf0220730ff511106aa0e0a8570ff00ee57d7a6f24e30f592a10cae1deffac9e13b990012102b8d567bcd6328fd48a429f9cf4b315b859a58fd28c5088ef3cb1d98125fc4e8dffffffff02364f1c00000000001976a91439a02793b418de8ec748dd75382656453dc99bcb88ac40420f000000000017a9145780b80be32e117f675d6e0ada13ba799bf248e98700000000");
    Transaction transaction = new Transaction(params, bytes);
    TransactionOutput output = transaction.getOutput(1);
    Transaction spendTx = new Transaction(params);
    Address address = new Address(params, "n3CFiCmBXVt5d3HXKQ15EFZyhPz4yj5F3H");
    Script outputScript = ScriptBuilder.createOutputScript(address);
    spendTx.addOutput(output.getValue(), outputScript);
    spendTx.addInput(output);
    Sha256Hash sighash = spendTx.hashForSignature(0, multisigScript, SigHash.ALL, false);
    ECKey.ECDSASignature party1Signature = key1.sign(sighash);
    ECKey.ECDSASignature party2Signature = key2.sign(sighash);
    TransactionSignature party1TransactionSignature =
        new TransactionSignature(party1Signature, SigHash.ALL, false);
    TransactionSignature party2TransactionSignature =
        new TransactionSignature(party2Signature, SigHash.ALL, false);

    // Create p2sh multisig input script
    Script inputScript =
        ScriptBuilder.createP2SHMultiSigInputScript(
            ImmutableList.of(party1TransactionSignature, party2TransactionSignature),
            multisigScript.getProgram());

    // Assert that the input script contains 4 chunks
    assertTrue(inputScript.getChunks().size() == 4);

    // Assert that the input script created contains the original multisig
    // script as the last chunk
    ScriptChunk scriptChunk = inputScript.getChunks().get(inputScript.getChunks().size() - 1);
    Assert.assertArrayEquals(scriptChunk.data, multisigScript.getProgram());

    // Create regular multisig input script
    inputScript =
        ScriptBuilder.createMultiSigInputScript(
            ImmutableList.of(party1TransactionSignature, party2TransactionSignature));

    // Assert that the input script only contains 3 chunks
    assertTrue(inputScript.getChunks().size() == 3);

    // Assert that the input script created does not end with the original
    // multisig script
    scriptChunk = inputScript.getChunks().get(inputScript.getChunks().size() - 1);
    Assert.assertThat(scriptChunk.data, IsNot.not(IsEqual.equalTo(multisigScript.getProgram())));
  }
示例#5
0
 @Test
 public void testUpdateLength() {
   NetworkParameters params = UnitTestParams.get();
   Block block =
       params
           .getGenesisBlock()
           .createNextBlockWithCoinbase(
               Block.BLOCK_VERSION_GENESIS, new ECKey().getPubKey(), Block.BLOCK_HEIGHT_GENESIS);
   assertEquals(block.bitcoinSerialize().length, block.length);
   final int origBlockLen = block.length;
   Transaction tx = new Transaction(params);
   // this is broken until the transaction has > 1 input + output (which is required anyway...)
   // assertTrue(tx.length == tx.bitcoinSerialize().length && tx.length == 8);
   byte[] outputScript = new byte[10];
   Arrays.fill(outputScript, (byte) ScriptOpCodes.OP_FALSE);
   tx.addOutput(new TransactionOutput(params, null, Coin.SATOSHI, outputScript));
   tx.addInput(
       new TransactionInput(
           params,
           null,
           new byte[] {(byte) ScriptOpCodes.OP_FALSE},
           new TransactionOutPoint(params, 0, Sha256Hash.of(new byte[] {1}))));
   int origTxLength = 8 + 2 + 8 + 1 + 10 + 40 + 1 + 1;
   assertEquals(tx.bitcoinSerialize().length, tx.length);
   assertEquals(origTxLength, tx.length);
   block.addTransaction(tx);
   assertEquals(block.bitcoinSerialize().length, block.length);
   assertEquals(origBlockLen + tx.length, block.length);
   block
       .getTransactions()
       .get(1)
       .getInputs()
       .get(0)
       .setScriptBytes(new byte[] {(byte) ScriptOpCodes.OP_FALSE, (byte) ScriptOpCodes.OP_FALSE});
   assertEquals(block.length, origBlockLen + tx.length);
   assertEquals(tx.length, origTxLength + 1);
   block.getTransactions().get(1).getInputs().get(0).setScriptBytes(new byte[] {});
   assertEquals(block.length, block.bitcoinSerialize().length);
   assertEquals(block.length, origBlockLen + tx.length);
   assertEquals(tx.length, origTxLength - 1);
   block
       .getTransactions()
       .get(1)
       .addInput(
           new TransactionInput(
               params,
               null,
               new byte[] {(byte) ScriptOpCodes.OP_FALSE},
               new TransactionOutPoint(params, 0, Sha256Hash.of(new byte[] {1}))));
   assertEquals(block.length, origBlockLen + tx.length);
   assertEquals(tx.length, origTxLength + 41); // - 1 + 40 + 1 + 1
 }
  @Before
  public void setUp() throws Exception {
    unitTestParams = UnitTestParams.get();
    wallet = new Wallet(unitTestParams);
    wallet.addKey(new ECKey());

    resetBlockStore();

    Transaction tx1 =
        createFakeTx(
            unitTestParams,
            Utils.toNanoCoins(2, 0),
            wallet.getKeys().get(0).toAddress(unitTestParams));

    // add a second input so can test granularity of byte cache.
    Transaction prevTx = new Transaction(unitTestParams);
    TransactionOutput prevOut =
        new TransactionOutput(
            unitTestParams,
            prevTx,
            Utils.toNanoCoins(1, 0),
            wallet.getKeys().get(0).toAddress(unitTestParams));
    prevTx.addOutput(prevOut);
    // Connect it.
    tx1.addInput(prevOut);

    Transaction tx2 =
        createFakeTx(
            unitTestParams, Utils.toNanoCoins(1, 0), new ECKey().toAddress(unitTestParams));

    Block b1 = createFakeBlock(blockStore, tx1, tx2).block;

    BitcoinSerializer bs = new BitcoinSerializer(unitTestParams);

    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    bs.serialize(tx1, bos);
    tx1BytesWithHeader = bos.toByteArray();
    tx1Bytes = tx1.bitcoinSerialize();

    bos.reset();
    bs.serialize(tx2, bos);
    tx2BytesWithHeader = bos.toByteArray();
    tx2Bytes = tx2.bitcoinSerialize();

    bos.reset();
    bs.serialize(b1, bos);
    b1BytesWithHeader = bos.toByteArray();
    b1Bytes = b1.bitcoinSerialize();
  }
 @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 skipScripts() throws Exception {
    store = createStore(params, 10);
    chain = new FullPrunedBlockChain(params, store);

    // Check that we aren't accidentally leaving any references
    // to the full StoredUndoableBlock's lying around (ie memory leaks)

    ECKey outKey = new ECKey();
    int height = 1;

    // Build some blocks on genesis block to create a spendable output
    Block rollingBlock =
        params
            .getGenesisBlock()
            .createNextBlockWithCoinbase(Block.BLOCK_VERSION_GENESIS, outKey.getPubKey(), height++);
    chain.add(rollingBlock);
    TransactionOutput spendableOutput = rollingBlock.getTransactions().get(0).getOutput(0);
    for (int i = 1; i < params.getSpendableCoinbaseDepth(); i++) {
      rollingBlock =
          rollingBlock.createNextBlockWithCoinbase(
              Block.BLOCK_VERSION_GENESIS, outKey.getPubKey(), height++);
      chain.add(rollingBlock);
    }

    rollingBlock = rollingBlock.createNextBlock(null);
    Transaction t = new Transaction(params);
    t.addOutput(new TransactionOutput(params, t, FIFTY_COINS, new byte[] {}));
    TransactionInput input = t.addInput(spendableOutput);
    // Invalid script.
    input.clearScriptBytes();
    rollingBlock.addTransaction(t);
    rollingBlock.solve();
    chain.setRunScripts(false);
    try {
      chain.add(rollingBlock);
    } catch (VerificationException e) {
      fail();
    }
    try {
      store.close();
    } catch (Exception e) {
    }
  }
  public void testTransaction(
      NetworkParameters params, byte[] txBytes, boolean isChild, boolean lazy, boolean retain)
      throws Exception {

    // reference serializer to produce comparison serialization output after changes to
    // message structure.
    BitcoinSerializer bsRef = new BitcoinSerializer(params, false, false);
    ByteArrayOutputStream bos = new ByteArrayOutputStream();

    BitcoinSerializer bs = new BitcoinSerializer(params, lazy, retain);
    Transaction t1;
    Transaction tRef;
    t1 = (Transaction) bs.deserialize(new ByteArrayInputStream(txBytes));
    tRef = (Transaction) bsRef.deserialize(new ByteArrayInputStream(txBytes));

    // verify our reference BitcoinSerializer produces matching byte array.
    bos.reset();
    bsRef.serialize(tRef, bos);
    assertTrue(Arrays.equals(bos.toByteArray(), txBytes));

    // check lazy and retain status survive both before and after a serialization
    assertEquals(!lazy, t1.isParsed());
    if (t1.isParsed()) assertEquals(retain, t1.isCached());

    serDeser(bs, t1, txBytes, null, null);

    assertEquals(lazy, !t1.isParsed());
    if (t1.isParsed()) assertEquals(retain, t1.isCached());

    // compare to ref tx
    bos.reset();
    bsRef.serialize(tRef, bos);
    serDeser(bs, t1, bos.toByteArray(), null, null);

    // retrieve a value from a child
    t1.getInputs();
    assertTrue(t1.isParsed());
    if (t1.getInputs().size() > 0) {
      assertTrue(t1.isParsed());
      TransactionInput tin = t1.getInputs().get(0);
      assertEquals(!lazy, tin.isParsed());
      if (tin.isParsed()) assertEquals(retain, tin.isCached());

      // does it still match ref tx?
      serDeser(bs, t1, bos.toByteArray(), null, null);
    }

    // refresh tx
    t1 = (Transaction) bs.deserialize(new ByteArrayInputStream(txBytes));
    tRef = (Transaction) bsRef.deserialize(new ByteArrayInputStream(txBytes));

    // add an input
    if (t1.getInputs().size() > 0) {

      t1.addInput(t1.getInputs().get(0));

      // replicate on reference tx
      tRef.addInput(tRef.getInputs().get(0));

      assertFalse(t1.isCached());
      assertTrue(t1.isParsed());

      bos.reset();
      bsRef.serialize(tRef, bos);
      byte[] source = bos.toByteArray();
      // confirm we still match the reference tx.
      serDeser(bs, t1, source, null, null);
    }
  }
  public void testBlock(byte[] blockBytes, boolean isChild, boolean lazy, boolean retain)
      throws Exception {
    // reference serializer to produce comparison serialization output after changes to
    // message structure.
    BitcoinSerializer bsRef = new BitcoinSerializer(unitTestParams, false, false);
    ByteArrayOutputStream bos = new ByteArrayOutputStream();

    BitcoinSerializer bs = new BitcoinSerializer(unitTestParams, lazy, retain);
    Block b1;
    Block bRef;
    b1 = (Block) bs.deserialize(new ByteArrayInputStream(blockBytes));
    bRef = (Block) bsRef.deserialize(new ByteArrayInputStream(blockBytes));

    // verify our reference BitcoinSerializer produces matching byte array.
    bos.reset();
    bsRef.serialize(bRef, bos);
    assertTrue(Arrays.equals(bos.toByteArray(), blockBytes));

    // check lazy and retain status survive both before and after a serialization
    assertEquals(!lazy, b1.isParsedTransactions());
    assertEquals(!lazy, b1.isParsedHeader());
    if (b1.isParsedHeader()) assertEquals(retain, b1.isHeaderBytesValid());
    if (b1.isParsedTransactions()) assertEquals(retain, b1.isTransactionBytesValid());

    serDeser(bs, b1, blockBytes, null, null);

    assertEquals(!lazy, b1.isParsedTransactions());
    assertEquals(!lazy, b1.isParsedHeader());
    if (b1.isParsedHeader()) assertEquals(retain, b1.isHeaderBytesValid());
    if (b1.isParsedTransactions()) assertEquals(retain, b1.isTransactionBytesValid());

    // compare to ref block
    bos.reset();
    bsRef.serialize(bRef, bos);
    serDeser(bs, b1, bos.toByteArray(), null, null);

    // retrieve a value from a child
    b1.getTransactions();
    assertTrue(b1.isParsedTransactions());
    if (b1.getTransactions().size() > 0) {
      assertTrue(b1.isParsedTransactions());
      Transaction tx1 = b1.getTransactions().get(0);

      // this will always be true for all children of a block once they are retrieved.
      // the tx child inputs/outputs may not be parsed however.

      // no longer forced to parse if length not provided.
      // assertEquals(true, tx1.isParsed());
      if (tx1.isParsed()) assertEquals(retain, tx1.isCached());
      else assertTrue(tx1.isCached());

      // does it still match ref block?
      serDeser(bs, b1, bos.toByteArray(), null, null);
    }

    // refresh block
    b1 = (Block) bs.deserialize(new ByteArrayInputStream(blockBytes));
    bRef = (Block) bsRef.deserialize(new ByteArrayInputStream(blockBytes));

    // retrieve a value from header
    b1.getDifficultyTarget();
    assertTrue(b1.isParsedHeader());
    assertEquals(lazy, !b1.isParsedTransactions());

    // does it still match ref block?
    serDeser(bs, b1, bos.toByteArray(), null, null);

    // refresh block
    b1 = (Block) bs.deserialize(new ByteArrayInputStream(blockBytes));
    bRef = (Block) bsRef.deserialize(new ByteArrayInputStream(blockBytes));

    // retrieve a value from a child and header
    b1.getDifficultyTarget();
    assertTrue(b1.isParsedHeader());
    assertEquals(lazy, !b1.isParsedTransactions());

    b1.getTransactions();
    assertTrue(b1.isParsedTransactions());
    if (b1.getTransactions().size() > 0) {
      assertTrue(b1.isParsedTransactions());
      Transaction tx1 = b1.getTransactions().get(0);

      // no longer forced to parse if length not provided.
      // assertEquals(true, tx1.isParsed());

      if (tx1.isParsed()) assertEquals(retain, tx1.isCached());
      else assertTrue(tx1.isCached());
    }
    // does it still match ref block?
    serDeser(bs, b1, bos.toByteArray(), null, null);

    // refresh block
    b1 = (Block) bs.deserialize(new ByteArrayInputStream(blockBytes));
    bRef = (Block) bsRef.deserialize(new ByteArrayInputStream(blockBytes));

    // change a value in header
    b1.setNonce(23);
    bRef.setNonce(23);
    assertTrue(b1.isParsedHeader());
    assertEquals(lazy, !b1.isParsedTransactions());
    assertFalse(b1.isHeaderBytesValid());
    if (b1.isParsedTransactions()) assertEquals(retain, b1.isTransactionBytesValid());
    else assertEquals(true, b1.isTransactionBytesValid());
    // does it still match ref block?
    bos.reset();
    bsRef.serialize(bRef, bos);
    serDeser(bs, b1, bos.toByteArray(), null, null);

    // refresh block
    b1 = (Block) bs.deserialize(new ByteArrayInputStream(blockBytes));
    bRef = (Block) bsRef.deserialize(new ByteArrayInputStream(blockBytes));

    // retrieve a value from a child of a child
    b1.getTransactions();
    if (b1.getTransactions().size() > 0) {
      Transaction tx1 = b1.getTransactions().get(0);

      TransactionInput tin = tx1.getInputs().get(0);

      assertTrue(tx1.isParsed());
      assertTrue(b1.isParsedTransactions());
      assertEquals(!lazy, b1.isParsedHeader());

      assertEquals(!lazy, tin.isParsed());
      assertEquals(tin.isParsed() ? retain : true, tin.isCached());

      // does it still match ref tx?
      bos.reset();
      bsRef.serialize(bRef, bos);
      serDeser(bs, b1, bos.toByteArray(), null, null);
    }

    // refresh block
    b1 = (Block) bs.deserialize(new ByteArrayInputStream(blockBytes));
    bRef = (Block) bsRef.deserialize(new ByteArrayInputStream(blockBytes));

    // add an input
    b1.getTransactions();
    if (b1.getTransactions().size() > 0) {
      Transaction tx1 = b1.getTransactions().get(0);

      if (tx1.getInputs().size() > 0) {
        tx1.addInput(tx1.getInputs().get(0));
        // replicate on reference tx
        bRef.getTransactions().get(0).addInput(bRef.getTransactions().get(0).getInputs().get(0));

        assertFalse(tx1.isCached());
        assertTrue(tx1.isParsed());
        assertFalse(b1.isTransactionBytesValid());
        assertTrue(b1.isParsedHeader());

        // confirm sibling cache status was unaffected
        if (tx1.getInputs().size() > 1) {
          boolean parsed = tx1.getInputs().get(1).isParsed();
          assertEquals(parsed ? retain : true, tx1.getInputs().get(1).isCached());
          assertEquals(!lazy, parsed);
        }

        // this has to be false. Altering a tx invalidates the merkle root.
        // when we have seperate merkle caching then the entire header won't need to be
        // invalidated.
        assertFalse(b1.isHeaderBytesValid());

        bos.reset();
        bsRef.serialize(bRef, bos);
        byte[] source = bos.toByteArray();
        // confirm we still match the reference tx.
        serDeser(bs, b1, source, null, null);
      }

      // does it still match ref tx?
      bos.reset();
      bsRef.serialize(bRef, bos);
      serDeser(bs, b1, bos.toByteArray(), null, null);
    }

    // refresh block
    b1 = (Block) bs.deserialize(new ByteArrayInputStream(blockBytes));
    Block b2 = (Block) bs.deserialize(new ByteArrayInputStream(blockBytes));
    bRef = (Block) bsRef.deserialize(new ByteArrayInputStream(blockBytes));
    Block bRef2 = (Block) bsRef.deserialize(new ByteArrayInputStream(blockBytes));

    // reparent an input
    b1.getTransactions();
    if (b1.getTransactions().size() > 0) {
      Transaction tx1 = b1.getTransactions().get(0);
      Transaction tx2 = b2.getTransactions().get(0);

      if (tx1.getInputs().size() > 0) {
        TransactionInput fromTx1 = tx1.getInputs().get(0);
        tx2.addInput(fromTx1);

        // replicate on reference tx
        TransactionInput fromTxRef = bRef.getTransactions().get(0).getInputs().get(0);
        bRef2.getTransactions().get(0).addInput(fromTxRef);

        // b1 hasn't changed but it's no longer in the parent
        // chain of fromTx1 so has to have been uncached since it won't be
        // notified of changes throught the parent chain anymore.
        assertFalse(b1.isTransactionBytesValid());

        // b2 should have it's cache invalidated because it has changed.
        assertFalse(b2.isTransactionBytesValid());

        bos.reset();
        bsRef.serialize(bRef2, bos);
        byte[] source = bos.toByteArray();
        // confirm altered block matches altered ref block.
        serDeser(bs, b2, source, null, null);
      }

      // does unaltered block still match ref block?
      bos.reset();
      bsRef.serialize(bRef, bos);
      serDeser(bs, b1, bos.toByteArray(), null, null);

      // how about if we refresh it?
      bRef = (Block) bsRef.deserialize(new ByteArrayInputStream(blockBytes));
      bos.reset();
      bsRef.serialize(bRef, bos);
      serDeser(bs, b1, bos.toByteArray(), null, null);
    }
  }
示例#11
0
 private void checkTimeLockedDependency(boolean shouldAccept, boolean useNotFound)
     throws Exception {
   // Initial setup.
   connectWithVersion(useNotFound ? 70001 : 60001);
   ECKey key = new ECKey();
   Wallet wallet = new Wallet(unitTestParams);
   wallet.addKey(key);
   wallet.setAcceptRiskyTransactions(shouldAccept);
   peer.addWallet(wallet);
   final Transaction[] vtx = new Transaction[1];
   wallet.addEventListener(
       new AbstractWalletEventListener() {
         @Override
         public void onCoinsReceived(
             Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) {
           vtx[0] = tx;
         }
       });
   // t1 -> t2 [locked] -> t3 (not available)
   Transaction t2 = new Transaction(unitTestParams);
   t2.setLockTime(999999);
   // Add a fake input to t3 that goes nowhere.
   Sha256Hash t3 = Sha256Hash.create("abc".getBytes(Charset.forName("UTF-8")));
   t2.addInput(
       new TransactionInput(
           unitTestParams, t2, new byte[] {}, new TransactionOutPoint(unitTestParams, 0, t3)));
   t2.getInput(0).setSequenceNumber(0xDEADBEEF);
   t2.addOutput(Utils.toNanoCoins(1, 0), new ECKey());
   Transaction t1 = new Transaction(unitTestParams);
   t1.addInput(t2.getOutput(0));
   t1.addOutput(Utils.toNanoCoins(1, 0), key); // Make it relevant.
   // Announce t1.
   InventoryMessage inv = new InventoryMessage(unitTestParams);
   inv.addTransaction(t1);
   inbound(writeTarget, inv);
   // Send it.
   GetDataMessage getdata = (GetDataMessage) outbound(writeTarget);
   assertEquals(t1.getHash(), getdata.getItems().get(0).hash);
   inbound(writeTarget, t1);
   // Nothing arrived at our event listener yet.
   assertNull(vtx[0]);
   // We request t2.
   getdata = (GetDataMessage) outbound(writeTarget);
   assertEquals(t2.getHash(), getdata.getItems().get(0).hash);
   inbound(writeTarget, t2);
   if (!useNotFound) bouncePing();
   // We request t3.
   getdata = (GetDataMessage) outbound(writeTarget);
   assertEquals(t3, getdata.getItems().get(0).hash);
   // Can't find it: bottom of tree.
   if (useNotFound) {
     NotFoundMessage notFound = new NotFoundMessage(unitTestParams);
     notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, t3));
     inbound(writeTarget, notFound);
   } else {
     bouncePing();
   }
   pingAndWait(writeTarget);
   Threading.waitForUserCode();
   // We're done but still not notified because it was timelocked.
   if (shouldAccept) assertNotNull(vtx[0]);
   else assertNull(vtx[0]);
 }
示例#12
0
  public void recursiveDownload(boolean useNotFound) throws Exception {
    // Using ping or notfound?
    connectWithVersion(useNotFound ? 70001 : 60001);
    // Check that we can download all dependencies of an unconfirmed relevant transaction from the
    // mempool.
    ECKey to = new ECKey();

    final Transaction[] onTx = new Transaction[1];
    peer.addEventListener(
        new AbstractPeerEventListener() {
          @Override
          public void onTransaction(Peer peer1, Transaction t) {
            onTx[0] = t;
          }
        },
        Threading.SAME_THREAD);

    // Make the some fake transactions in the following graph:
    //   t1 -> t2 -> [t5]
    //      -> t3 -> t4 -> [t6]
    //      -> [t7]
    //      -> [t8]
    // The ones in brackets are assumed to be in the chain and are represented only by hashes.
    Transaction t2 = TestUtils.createFakeTx(unitTestParams, Utils.toNanoCoins(1, 0), to);
    Sha256Hash t5 = t2.getInput(0).getOutpoint().getHash();
    Transaction t4 = TestUtils.createFakeTx(unitTestParams, Utils.toNanoCoins(1, 0), new ECKey());
    Sha256Hash t6 = t4.getInput(0).getOutpoint().getHash();
    t4.addOutput(Utils.toNanoCoins(1, 0), new ECKey());
    Transaction t3 = new Transaction(unitTestParams);
    t3.addInput(t4.getOutput(0));
    t3.addOutput(Utils.toNanoCoins(1, 0), new ECKey());
    Transaction t1 = new Transaction(unitTestParams);
    t1.addInput(t2.getOutput(0));
    t1.addInput(t3.getOutput(0));
    Sha256Hash someHash =
        new Sha256Hash("2b801dd82f01d17bbde881687bf72bc62e2faa8ab8133d36fcb8c3abe7459da6");
    t1.addInput(
        new TransactionInput(
            unitTestParams,
            t1,
            new byte[] {},
            new TransactionOutPoint(unitTestParams, 0, someHash)));
    Sha256Hash anotherHash =
        new Sha256Hash("3b801dd82f01d17bbde881687bf72bc62e2faa8ab8133d36fcb8c3abe7459da6");
    t1.addInput(
        new TransactionInput(
            unitTestParams,
            t1,
            new byte[] {},
            new TransactionOutPoint(unitTestParams, 1, anotherHash)));
    t1.addOutput(Utils.toNanoCoins(1, 0), to);
    t1 = TestUtils.roundTripTransaction(unitTestParams, t1);
    t2 = TestUtils.roundTripTransaction(unitTestParams, t2);
    t3 = TestUtils.roundTripTransaction(unitTestParams, t3);
    t4 = TestUtils.roundTripTransaction(unitTestParams, t4);

    // Announce the first one. Wait for it to be downloaded.
    InventoryMessage inv = new InventoryMessage(unitTestParams);
    inv.addTransaction(t1);
    inbound(writeTarget, inv);
    GetDataMessage getdata = (GetDataMessage) outbound(writeTarget);
    Threading.waitForUserCode();
    assertEquals(t1.getHash(), getdata.getItems().get(0).hash);
    inbound(writeTarget, t1);
    pingAndWait(writeTarget);
    assertEquals(t1, onTx[0]);
    // We want its dependencies so ask for them.
    ListenableFuture<List<Transaction>> futures = peer.downloadDependencies(t1);
    assertFalse(futures.isDone());
    // It will recursively ask for the dependencies of t1: t2, t3, someHash and anotherHash.
    getdata = (GetDataMessage) outbound(writeTarget);
    assertEquals(4, getdata.getItems().size());
    assertEquals(t2.getHash(), getdata.getItems().get(0).hash);
    assertEquals(t3.getHash(), getdata.getItems().get(1).hash);
    assertEquals(someHash, getdata.getItems().get(2).hash);
    assertEquals(anotherHash, getdata.getItems().get(3).hash);
    long nonce = -1;
    if (!useNotFound) nonce = ((Ping) outbound(writeTarget)).getNonce();
    // For some random reason, t4 is delivered at this point before it's needed - perhaps it was a
    // Bloom filter
    // false positive. We do this to check that the mempool is being checked for seen transactions
    // before
    // requesting them.
    inbound(writeTarget, t4);
    // Deliver the requested transactions.
    inbound(writeTarget, t2);
    inbound(writeTarget, t3);
    if (useNotFound) {
      NotFoundMessage notFound = new NotFoundMessage(unitTestParams);
      notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, someHash));
      notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, anotherHash));
      inbound(writeTarget, notFound);
    } else {
      inbound(writeTarget, new Pong(nonce));
    }
    assertFalse(futures.isDone());
    // It will recursively ask for the dependencies of t2: t5 and t4, but not t3 because it already
    // found t4.
    getdata = (GetDataMessage) outbound(writeTarget);
    assertEquals(getdata.getItems().get(0).hash, t2.getInput(0).getOutpoint().getHash());
    // t5 isn't found and t4 is.
    if (useNotFound) {
      NotFoundMessage notFound = new NotFoundMessage(unitTestParams);
      notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, t5));
      inbound(writeTarget, notFound);
    } else {
      bouncePing();
    }
    assertFalse(futures.isDone());
    // Continue to explore the t4 branch and ask for t6, which is in the chain.
    getdata = (GetDataMessage) outbound(writeTarget);
    assertEquals(t6, getdata.getItems().get(0).hash);
    if (useNotFound) {
      NotFoundMessage notFound = new NotFoundMessage(unitTestParams);
      notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, t6));
      inbound(writeTarget, notFound);
    } else {
      bouncePing();
    }
    pingAndWait(writeTarget);
    // That's it, we explored the entire tree.
    assertTrue(futures.isDone());
    List<Transaction> results = futures.get();
    assertTrue(results.contains(t2));
    assertTrue(results.contains(t3));
    assertTrue(results.contains(t4));
  }