@Test public void serializationUnencrypted() throws UnreadableWalletException { Utils.setMockClock(); Date now = Utils.now(); final ECKey key1 = new ECKey(); Utils.rollMockClock(5000); final ECKey key2 = new ECKey(); chain.importKeys(ImmutableList.of(key1, key2)); List<Protos.Key> keys = chain.serializeToProtobuf(); assertEquals(2, keys.size()); assertArrayEquals(key1.getPubKey(), keys.get(0).getPublicKey().toByteArray()); assertArrayEquals(key2.getPubKey(), keys.get(1).getPublicKey().toByteArray()); assertArrayEquals(key1.getPrivKeyBytes(), keys.get(0).getSecretBytes().toByteArray()); assertArrayEquals(key2.getPrivKeyBytes(), keys.get(1).getSecretBytes().toByteArray()); long normTime = (long) (Math.floor(now.getTime() / 1000) * 1000); assertEquals(normTime, keys.get(0).getCreationTimestamp()); assertEquals(normTime + 5000 * 1000, keys.get(1).getCreationTimestamp()); chain = BasicKeyChain.fromProtobufUnencrypted(keys); assertEquals(2, chain.getKeys().size()); assertEquals(key1, chain.getKeys().get(0)); assertEquals(key2, chain.getKeys().get(1)); }
Utils.rollMockClock(60 * 10); Transaction tx2 = sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, valueOf(0, 5)); Utils.rollMockClock(60 * 5); Transaction tx3 = wallet.createSend(OTHER_ADDRESS, valueOf(0, 5));
@Test public void earliestKeyTime() throws Exception { long now = Utils.currentTimeSeconds(); // mock long yesterday = now - 86400; assertEquals(now, group.getEarliestKeyCreationTime()); Utils.rollMockClock(10000); group.freshKey(KeyChain.KeyPurpose.RECEIVE_FUNDS); Utils.rollMockClock(10000); group.freshKey(KeyChain.KeyPurpose.RECEIVE_FUNDS); // Check that all keys are assumed to be created at the same instant the seed is. assertEquals(now, group.getEarliestKeyCreationTime()); ECKey key = new ECKey(); key.setCreationTimeSeconds(yesterday); group.importKeys(key); assertEquals(yesterday, group.getEarliestKeyCreationTime()); }
@Test public void keysBeforeAndAfter() throws Exception { Utils.setMockClock(); long now = Utils.currentTimeSeconds(); final ECKey key1 = new ECKey(); Utils.rollMockClock(86400); final ECKey key2 = new ECKey(); final List<ECKey> keys = Lists.newArrayList(key1, key2); assertEquals(2, chain.importKeys(keys)); assertNull(chain.findOldestKeyAfter(now + 86400 * 2)); assertEquals(key1, chain.findOldestKeyAfter(now - 1)); assertEquals(key2, chain.findOldestKeyAfter(now + 86400 - 1)); assertEquals(2, chain.findKeysBefore(now + 86400 * 2).size()); assertEquals(1, chain.findKeysBefore(now + 1).size()); assertEquals(0, chain.findKeysBefore(now - 1).size()); } }
ECKey badKey = ECKey.fromPrivate(Utils.HEX.decode("00905b93f990267f4104f316261fc10f9f983551f9ef160854f40102eb71cffdbb")); badKey.setCreationTimeSeconds(Utils.currentTimeSeconds()); Utils.rollMockClock(86400); ECKey goodKey = ECKey.fromPrivate(Utils.HEX.decode("00905b93f990267f4104f316261fc10f9f983551f9ef160854f40102eb71cffdcc")); goodKey.setCreationTimeSeconds(Utils.currentTimeSeconds()); Utils.rollMockClock(86400); wallet = new Wallet(PARAMS, kcg); // This avoids the automatic HD initialisation assertTrue(fChains.get().isEmpty());
@Test public void keyCreationTime() throws Exception { Utils.setMockClock(); long now = Utils.currentTimeSeconds(); wallet = new Wallet(PARAMS); assertEquals(now, wallet.getEarliestKeyCreationTime()); Utils.rollMockClock(60); wallet.freshReceiveKey(); assertEquals(now, wallet.getEarliestKeyCreationTime()); }
@Test public void scriptCreationTime() throws Exception { Utils.setMockClock(); long now = Utils.currentTimeSeconds(); wallet = new Wallet(PARAMS); assertEquals(now, wallet.getEarliestKeyCreationTime()); Utils.rollMockClock(-120); wallet.addWatchedAddress(OTHER_ADDRESS); wallet.freshReceiveKey(); assertEquals(now - 120, wallet.getEarliestKeyCreationTime()); }
@Test public void importKeys() { long now = Utils.currentTimeSeconds(); Utils.setMockClock(now); final ECKey key1 = new ECKey(); Utils.rollMockClock(86400); final ECKey key2 = new ECKey(); final ArrayList<ECKey> keys = Lists.newArrayList(key1, key2); // Import two keys, check the event is correct. assertEquals(2, chain.importKeys(keys)); assertEquals(2, chain.numKeys()); assertTrue(onKeysAddedRan.getAndSet(false)); assertArrayEquals(keys.toArray(), onKeysAdded.get().toArray()); assertEquals(now, chain.getEarliestKeyCreationTime()); // Check we ignore duplicates. final ECKey newKey = new ECKey(); keys.add(newKey); assertEquals(1, chain.importKeys(keys)); assertTrue(onKeysAddedRan.getAndSet(false)); assertEquals(newKey, onKeysAdded.getAndSet(null).get(0)); assertEquals(0, chain.importKeys(keys)); assertFalse(onKeysAddedRan.getAndSet(false)); assertNull(onKeysAdded.get()); assertTrue(chain.hasKey(key1)); assertTrue(chain.hasKey(key2)); assertEquals(key1, chain.findKeyFromPubHash(key1.getPubKeyHash())); assertEquals(key2, chain.findKeyFromPubKey(key2.getPubKey())); assertNull(chain.findKeyFromPubKey(key2.getPubKeyHash())); }
@Test public void deterministicUpgradeRotating() throws Exception { group = new KeyChainGroup(PARAMS); group.setLookaheadSize(LOOKAHEAD_SIZE); // Don't want slow tests. long now = Utils.currentTimeSeconds(); ECKey key1 = new ECKey(); Utils.rollMockClock(86400); ECKey key2 = new ECKey(); Utils.rollMockClock(86400); ECKey key3 = new ECKey(); group.importKeys(key2, key1, key3); group.upgradeToDeterministic(now + 10, null); DeterministicSeed seed = group.getActiveKeyChain().getSeed(); assertNotNull(seed); // Check we used the right key: oldest non rotating. byte[] truncatedBytes = Arrays.copyOfRange(key2.getSecretBytes(), 0, 16); assertArrayEquals(seed.getEntropyBytes(), truncatedBytes); }
@Test public void keyRotationHD() throws Exception { // Test that if we rotate an HD chain, a new one is created and all arrivals on the old keys are moved. Utils.setMockClock(); wallet = new Wallet(PARAMS); ECKey key1 = wallet.freshReceiveKey(); ECKey key2 = wallet.freshReceiveKey(); sendMoneyToWallet(wallet, AbstractBlockChain.NewBlockType.BEST_CHAIN, CENT, key1.toAddress(PARAMS)); sendMoneyToWallet(wallet, AbstractBlockChain.NewBlockType.BEST_CHAIN, CENT, key2.toAddress(PARAMS)); DeterministicKey watchKey1 = wallet.getWatchingKey(); // A day later, we get compromised. Utils.rollMockClock(86400); wallet.setKeyRotationTime(Utils.currentTimeSeconds()); List<Transaction> txns = wallet.doMaintenance(null, false).get(); assertEquals(1, txns.size()); DeterministicKey watchKey2 = wallet.getWatchingKey(); assertNotEquals(watchKey1, watchKey2); }
public void fragmentedReKeying() throws Exception { // Send lots of small coins and check the fee is correct. ECKey key = wallet.freshReceiveKey(); Address address = key.toAddress(PARAMS); Utils.setMockClock(); Utils.rollMockClock(86400); for (int i = 0; i < 800; i++) { sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, CENT, address); } MockTransactionBroadcaster broadcaster = new MockTransactionBroadcaster(wallet); Date compromise = Utils.now(); Utils.rollMockClock(86400); wallet.freshReceiveKey(); wallet.setKeyRotationTime(compromise); wallet.doMaintenance(null, true); Transaction tx = broadcaster.waitForTransactionAndSucceed(); final Coin valueSentToMe = tx.getValueSentToMe(wallet); Coin fee = tx.getValueSentFromMe(wallet).subtract(valueSentToMe); assertEquals(Coin.valueOf(900000), fee); assertEquals(KeyTimeCoinSelector.MAX_SIMULTANEOUS_INPUTS, tx.getInputs().size()); assertEquals(Coin.valueOf(599100000), valueSentToMe); tx = broadcaster.waitForTransaction(); assertNotNull(tx); assertEquals(200, tx.getInputs().size()); }
Utils.rollMockClock(60 * 10); // 10 minutes later. Block b2 = makeSolvedTestBlock(b1); b2.setTime(Utils.currentTimeSeconds()); b2.solve(); Utils.rollMockClock(60 * 10); // 10 minutes later. Block b3 = makeSolvedTestBlock(b2); b3.setTime(Utils.currentTimeSeconds()); b3.solve(); Utils.rollMockClock(60 * 10); Block b4 = makeSolvedTestBlock(b3); b4.setTime(Utils.currentTimeSeconds());
@Test public void pingPong() throws Exception { connect(); Utils.setMockClock(); // No ping pong happened yet. assertEquals(Long.MAX_VALUE, peer.getLastPingTime()); assertEquals(Long.MAX_VALUE, peer.getPingTime()); ListenableFuture<Long> future = peer.ping(); assertEquals(Long.MAX_VALUE, peer.getLastPingTime()); assertEquals(Long.MAX_VALUE, peer.getPingTime()); assertFalse(future.isDone()); Ping pingMsg = (Ping) outbound(writeTarget); Utils.rollMockClock(5); // The pong is returned. inbound(writeTarget, new Pong(pingMsg.getNonce())); pingAndWait(writeTarget); assertTrue(future.isDone()); long elapsed = future.get(); assertTrue("" + elapsed, elapsed > 1000); assertEquals(elapsed, peer.getLastPingTime()); assertEquals(elapsed, peer.getPingTime()); // Do it again and make sure it affects the average. future = peer.ping(); pingMsg = (Ping) outbound(writeTarget); Utils.rollMockClock(50); inbound(writeTarget, new Pong(pingMsg.getNonce())); elapsed = future.get(); assertEquals(elapsed, peer.getLastPingTime()); assertEquals(7250, peer.getPingTime()); }
@Test public void difficultyTransitions() throws Exception { // Add a bunch of blocks in a loop until we reach a difficulty transition point. The unit test params have an // artificially shortened period. Block prev = PARAMS.getGenesisBlock(); Utils.setMockClock(System.currentTimeMillis()/1000); for (int height = 0; height < PARAMS.getInterval() - 1; height++) { Block newBlock = prev.createNextBlock(coinbaseTo, 1, Utils.currentTimeSeconds(), height); assertTrue(chain.add(newBlock)); prev = newBlock; // The fake chain should seem to be "fast" for the purposes of difficulty calculations. Utils.rollMockClock(2); } // Now add another block that has no difficulty adjustment, it should be rejected. try { chain.add(prev.createNextBlock(coinbaseTo, 1, Utils.currentTimeSeconds(), PARAMS.getInterval())); fail(); } catch (VerificationException e) { } // Create a new block with the right difficulty target given our blistering speed relative to the huge amount // of time it's supposed to take (set in the unit test network parameters). Block b = prev.createNextBlock(coinbaseTo, 1, Utils.currentTimeSeconds(), PARAMS.getInterval() + 1); b.setDifficultyTarget(0x201fFFFFL); b.solve(); assertTrue(chain.add(b)); // Successfully traversed a difficulty transition period. }
public void encryption(boolean withImported) throws Exception { Utils.rollMockClock(0); long now = Utils.currentTimeSeconds(); ECKey a = group.freshKey(KeyChain.KeyPurpose.RECEIVE_FUNDS); assertEquals(now, group.getEarliestKeyCreationTime()); Utils.rollMockClock(-86400); long yesterday = Utils.currentTimeSeconds(); ECKey b = new ECKey();
Utils.rollMockClock(60 * 60 * 24 + 60 * 5); // Client announces refund 5 minutes after expire time StoredPaymentChannelClientStates newClientStates = new StoredPaymentChannelClientStates(wallet, mockBroadcaster); newClientStates.deserializeWalletExtension(wallet, clientStoredChannels.serializeWalletExtension());
Utils.rollMockClock(60*60*22); Utils.rollMockClock(60 * 60 * 2 + 60 * 5);
@Test public void deterministicUpgradeUnencrypted() throws Exception { // Check that a group that contains only random keys has its HD chain created using the private key bytes of // the oldest random key, so upgrading the same wallet twice gives the same outcome. group = new KeyChainGroup(PARAMS); group.setLookaheadSize(LOOKAHEAD_SIZE); // Don't want slow tests. ECKey key1 = new ECKey(); Utils.rollMockClock(86400); ECKey key2 = new ECKey(); group.importKeys(key2, key1); List<Protos.Key> protobufs = group.serializeToProtobuf(); group.upgradeToDeterministic(0, null); assertFalse(group.isDeterministicUpgradeRequired()); DeterministicKey dkey1 = group.freshKey(KeyChain.KeyPurpose.RECEIVE_FUNDS); DeterministicSeed seed1 = group.getActiveKeyChain().getSeed(); assertNotNull(seed1); group = KeyChainGroup.fromProtobufUnencrypted(PARAMS, protobufs); group.upgradeToDeterministic(0, null); // Should give same result as last time. DeterministicKey dkey2 = group.freshKey(KeyChain.KeyPurpose.RECEIVE_FUNDS); DeterministicSeed seed2 = group.getActiveKeyChain().getSeed(); assertEquals(seed1, seed2); assertEquals(dkey1, dkey2); // Check we used the right (oldest) key despite backwards import order. byte[] truncatedBytes = Arrays.copyOfRange(key1.getSecretBytes(), 0, 16); assertArrayEquals(seed1.getEntropyBytes(), truncatedBytes); }
Utils.rollMockClock(1); wallet.setKeyRotationTime(compromiseTime); assertTrue(wallet.isKeyRotating(key1));