public void timeLockedTransaction(boolean useNotFound) throws Exception { connectWithVersion(useNotFound ? 70001 : 60001); // Test that if we receive a relevant transaction that has a lock time, it doesn't result in a // notification // until we explicitly opt in to seeing those. ECKey key = new ECKey(); Wallet wallet = new Wallet(unitTestParams); wallet.addKey(key); 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; } }); // Send a normal relevant transaction, it's received correctly. Transaction t1 = TestUtils.createFakeTx(unitTestParams, Utils.toNanoCoins(1, 0), key); inbound(writeTarget, t1); GetDataMessage getdata = (GetDataMessage) outbound(writeTarget); if (useNotFound) { inbound(writeTarget, new NotFoundMessage(unitTestParams, getdata.getItems())); } else { bouncePing(); } pingAndWait(writeTarget); Threading.waitForUserCode(); assertNotNull(vtx[0]); vtx[0] = null; // Send a timelocked transaction, nothing happens. Transaction t2 = TestUtils.createFakeTx(unitTestParams, Utils.toNanoCoins(2, 0), key); t2.setLockTime(999999); inbound(writeTarget, t2); Threading.waitForUserCode(); assertNull(vtx[0]); // Now we want to hear about them. Send another, we are told about it. wallet.setAcceptRiskyTransactions(true); inbound(writeTarget, t2); getdata = (GetDataMessage) outbound(writeTarget); if (useNotFound) { inbound(writeTarget, new NotFoundMessage(unitTestParams, getdata.getItems())); } else { bouncePing(); } pingAndWait(writeTarget); Threading.waitForUserCode(); assertEquals(t2, vtx[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]); }
@Test public void testAppearedAtChainHeightDepthAndWorkDone() throws Exception { // Test the TransactionConfidence appearedAtChainHeight, depth and workDone field are stored. BlockChain chain = new BlockChain(params, myWallet, new MemoryBlockStore(params)); final ArrayList<Transaction> txns = new ArrayList<Transaction>(2); myWallet.addEventListener( new AbstractWalletEventListener() { @Override public void onCoinsReceived( Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) { txns.add(tx); } }); // Start by building two blocks on top of the genesis block. Block b1 = params.getGenesisBlock().createNextBlock(myAddress); BigInteger work1 = b1.getWork(); assertTrue(work1.signum() > 0); Block b2 = b1.createNextBlock(myAddress); BigInteger work2 = b2.getWork(); assertTrue(work2.signum() > 0); assertTrue(chain.add(b1)); assertTrue(chain.add(b2)); // We now have the following chain: // genesis -> b1 -> b2 // Check the transaction confidence levels are correct before wallet roundtrip. Threading.waitForUserCode(); assertEquals(2, txns.size()); TransactionConfidence confidence0 = txns.get(0).getConfidence(); TransactionConfidence confidence1 = txns.get(1).getConfidence(); assertEquals(1, confidence0.getAppearedAtChainHeight()); assertEquals(2, confidence1.getAppearedAtChainHeight()); assertEquals(2, confidence0.getDepthInBlocks()); assertEquals(1, confidence1.getDepthInBlocks()); // Roundtrip the wallet and check it has stored the depth and workDone. Wallet rebornWallet = roundTrip(myWallet); Set<Transaction> rebornTxns = rebornWallet.getTransactions(false); assertEquals(2, rebornTxns.size()); // The transactions are not guaranteed to be in the same order so sort them to be in chain // height order if required. Iterator<Transaction> it = rebornTxns.iterator(); Transaction txA = it.next(); Transaction txB = it.next(); Transaction rebornTx0, rebornTx1; if (txA.getConfidence().getAppearedAtChainHeight() == 1) { rebornTx0 = txA; rebornTx1 = txB; } else { rebornTx0 = txB; rebornTx1 = txA; } TransactionConfidence rebornConfidence0 = rebornTx0.getConfidence(); TransactionConfidence rebornConfidence1 = rebornTx1.getConfidence(); assertEquals(1, rebornConfidence0.getAppearedAtChainHeight()); assertEquals(2, rebornConfidence1.getAppearedAtChainHeight()); assertEquals(2, rebornConfidence0.getDepthInBlocks()); assertEquals(1, rebornConfidence1.getDepthInBlocks()); }