Java Code Examples for org.bitcoinj.core.Utils#setMockClock()

The following examples show how to use org.bitcoinj.core.Utils#setMockClock() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: BasicKeyChainTest.java    From green_android with GNU General Public License v3.0 6 votes vote down vote up
@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));
}
 
Example 2
Source File: WalletTest.java    From green_android with GNU General Public License v3.0 6 votes vote down vote up
@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);
}
 
Example 3
Source File: BasicKeyChainTest.java    From bcm-android with GNU General Public License v3.0 6 votes vote down vote up
@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());
}
 
Example 4
Source File: BasicKeyChainTest.java    From bcm-android with GNU General Public License v3.0 6 votes vote down vote up
@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));
}
 
Example 5
Source File: BasicKeyChainTest.java    From GreenBits with GNU General Public License v3.0 6 votes vote down vote up
@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));
}
 
Example 6
Source File: WalletTest.java    From GreenBits with GNU General Public License v3.0 6 votes vote down vote up
@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);
}
 
Example 7
Source File: WalletTest.java    From GreenBits with GNU General Public License v3.0 5 votes vote down vote up
@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());
}
 
Example 8
Source File: WalletTest.java    From green_android with GNU General Public License v3.0 5 votes vote down vote up
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());
}
 
Example 9
Source File: BasicKeyChainTest.java    From bcm-android with GNU General Public License v3.0 5 votes vote down vote up
@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()));
}
 
Example 10
Source File: DeterministicKeyChainTest.java    From bcm-android with GNU General Public License v3.0 5 votes vote down vote up
@Test
public void watchingChainArbitraryPath() throws UnreadableWalletException {
    Utils.setMockClock();
    DeterministicKey key1 = bip44chain.getKey(KeyChain.KeyPurpose.RECEIVE_FUNDS);
    DeterministicKey key2 = bip44chain.getKey(KeyChain.KeyPurpose.RECEIVE_FUNDS);
    DeterministicKey key3 = bip44chain.getKey(KeyChain.KeyPurpose.CHANGE);
    DeterministicKey key4 = bip44chain.getKey(KeyChain.KeyPurpose.CHANGE);

    DeterministicKey watchingKey = bip44chain.getWatchingKey();
    watchingKey = watchingKey.dropPrivateBytes().dropParent();
    watchingKey.setCreationTimeSeconds(100000);
    chain = DeterministicKeyChain.watch(watchingKey);
    assertEquals(100000, chain.getEarliestKeyCreationTime());
    chain.setLookaheadSize(10);
    chain.maybeLookAhead();

    assertEquals(key1.getPubKeyPoint(), chain.getKey(KeyChain.KeyPurpose.RECEIVE_FUNDS).getPubKeyPoint());
    assertEquals(key2.getPubKeyPoint(), chain.getKey(KeyChain.KeyPurpose.RECEIVE_FUNDS).getPubKeyPoint());
    final DeterministicKey key = chain.getKey(KeyChain.KeyPurpose.CHANGE);
    assertEquals(key3.getPubKeyPoint(), key.getPubKeyPoint());
    try {
        // Can't sign with a key from a watching chain.
        key.sign(Sha256Hash.ZERO_HASH);
        fail();
    } catch (ECKey.MissingPrivateKeyException e) {
        // Ignored.
    }
    // Test we can serialize and deserialize a watching chain OK.
    List<Protos.Key> serialization = chain.serializeToProtobuf();
    checkSerialization(serialization, "watching-wallet-arbitrary-path-serialization.txt");
    chain = DeterministicKeyChain.fromProtobuf(serialization, null).get(0);
    final DeterministicKey rekey4 = chain.getKey(KeyChain.KeyPurpose.CHANGE);
    assertEquals(key4.getPubKeyPoint(), rekey4.getPubKeyPoint());
}
 
Example 11
Source File: KeyChainGroupTest.java    From bcm-android with GNU General Public License v3.0 5 votes vote down vote up
@Before
public void setup() {
    BriefLogFormatter.init();
    Utils.setMockClock();
    group = new KeyChainGroup(MAINNET);
    group.setLookaheadSize(LOOKAHEAD_SIZE);   // Don't want slow tests.
    group.getActiveKeyChain();  // Force create a chain.

    watchingAccountKey = DeterministicKey.deserializeB58(null, XPUB, MAINNET);
}
 
Example 12
Source File: BasicKeyChainTest.java    From green_android with GNU General Public License v3.0 5 votes vote down vote up
@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()));
}
 
Example 13
Source File: WalletTest.java    From bcm-android with GNU General Public License v3.0 5 votes vote down vote up
@Test
public void keyCreationTime() throws Exception {
    Utils.setMockClock();
    long now = Utils.currentTimeSeconds();
    wallet = new Wallet(UNITTEST);
    assertEquals(now, wallet.getEarliestKeyCreationTime());
    Utils.rollMockClock(60);
    wallet.freshReceiveKey();
    assertEquals(now, wallet.getEarliestKeyCreationTime());
}
 
Example 14
Source File: WalletTest.java    From green_android with GNU General Public License v3.0 5 votes vote down vote up
@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());
}
 
Example 15
Source File: PaymentChannelServerTest.java    From GreenBits with GNU General Public License v3.0 5 votes vote down vote up
@Before
public void setUp() {
    broadcaster = createMock(TransactionBroadcaster.class);
    wallet = createMock(Wallet.class);
    connection = createMock(PaymentChannelServer.ServerConnection.class);
    serverVersionCapture = new Capture<TwoWayChannelMessage>();
    connection.sendToClient(capture(serverVersionCapture));
    Utils.setMockClock();
}
 
Example 16
Source File: PaymentChannelServerTest.java    From bcm-android with GNU General Public License v3.0 5 votes vote down vote up
@Before
public void setUp() {
    broadcaster = createMock(TransactionBroadcaster.class);
    wallet = createMock(Wallet.class);
    connection = createMock(PaymentChannelServer.ServerConnection.class);
    serverVersionCapture = new Capture<TwoWayChannelMessage>();
    connection.sendToClient(capture(serverVersionCapture));
    Utils.setMockClock();
}
 
Example 17
Source File: WalletTest.java    From bcm-android with GNU General Public License v3.0 5 votes vote down vote up
public void fragmentedReKeying() throws Exception {
    // Send lots of small coins and check the fee is correct.
    ECKey key = wallet.freshReceiveKey();
    Address address = LegacyAddress.fromKey(UNITTEST, key);
    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());
}
 
Example 18
Source File: PaymentChannelServerTest.java    From green_android with GNU General Public License v3.0 5 votes vote down vote up
@Before
public void setUp() {
    broadcaster = createMock(TransactionBroadcaster.class);
    wallet = createMock(Wallet.class);
    connection = createMock(PaymentChannelServer.ServerConnection.class);
    serverVersionCapture = new Capture<TwoWayChannelMessage>();
    connection.sendToClient(capture(serverVersionCapture));
    Utils.setMockClock();
}
 
Example 19
Source File: WalletTest.java    From GreenBits with GNU General Public License v3.0 4 votes vote down vote up
@SuppressWarnings("ConstantConditions")
@Test
public void keyRotationHD2() throws Exception {
    // Check we handle the following scenario: a weak random key is created, then some good random keys are created
    // but the weakness of the first isn't known yet. The wallet is upgraded to HD based on the weak key. Later, we
    // find out about the weakness and set the rotation time to after the bad key's creation date. A new HD chain
    // should be created based on the oldest known good key and the old chain + bad random key should rotate to it.

    // We fix the private keys just to make the test deterministic (last byte differs).
    Utils.setMockClock();
    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());

    // Do an upgrade based on the bad key.
    final AtomicReference<List<DeterministicKeyChain>> fChains = new AtomicReference<>();
    KeyChainGroup kcg = new KeyChainGroup(PARAMS) {

        {
            fChains.set(chains);
        }
    };
    kcg.importKeys(badKey, goodKey);
    Utils.rollMockClock(86400);
    wallet = new Wallet(PARAMS, kcg);   // This avoids the automatic HD initialisation
    assertTrue(fChains.get().isEmpty());
    wallet.upgradeToDeterministic(null);
    DeterministicKey badWatchingKey = wallet.getWatchingKey();
    assertEquals(badKey.getCreationTimeSeconds(), badWatchingKey.getCreationTimeSeconds());
    sendMoneyToWallet(wallet, AbstractBlockChain.NewBlockType.BEST_CHAIN, CENT, badWatchingKey.toAddress(PARAMS));

    // Now we set the rotation time to the time we started making good keys. This should create a new HD chain.
    wallet.setKeyRotationTime(goodKey.getCreationTimeSeconds());
    List<Transaction> txns = wallet.doMaintenance(null, false).get();
    assertEquals(1, txns.size());
    Address output = txns.get(0).getOutput(0).getAddressFromP2PKHScript(PARAMS);
    ECKey usedKey = wallet.findKeyFromPubHash(output.getHash160());
    assertEquals(goodKey.getCreationTimeSeconds(), usedKey.getCreationTimeSeconds());
    assertEquals(goodKey.getCreationTimeSeconds(), wallet.freshReceiveKey().getCreationTimeSeconds());
    assertEquals("mrM3TpCnav5YQuVA1xLercCGJH4DXujMtv", usedKey.toAddress(PARAMS).toString());
    DeterministicKeyChain c = fChains.get().get(1);
    assertEquals(c.getEarliestKeyCreationTime(), goodKey.getCreationTimeSeconds());
    assertEquals(2, fChains.get().size());

    // Commit the maint txns.
    wallet.commitTx(txns.get(0));

    // Check next maintenance does nothing.
    assertTrue(wallet.doMaintenance(null, false).get().isEmpty());
    assertEquals(c, fChains.get().get(1));
    assertEquals(2, fChains.get().size());
}
 
Example 20
Source File: WalletTest.java    From bcm-android with GNU General Public License v3.0 4 votes vote down vote up
@Test
public void keyRotationRandom() throws Exception {
    Utils.setMockClock();
    // Start with an empty wallet (no HD chain).
    wallet = new Wallet(UNITTEST);
    // Watch out for wallet-initiated broadcasts.
    MockTransactionBroadcaster broadcaster = new MockTransactionBroadcaster(wallet);
    // Send three cents to two different random keys, then add a key and mark the initial keys as compromised.
    ECKey key1 = new ECKey();
    key1.setCreationTimeSeconds(Utils.currentTimeSeconds() - (86400 * 2));
    ECKey key2 = new ECKey();
    key2.setCreationTimeSeconds(Utils.currentTimeSeconds() - 86400);
    wallet.importKey(key1);
    wallet.importKey(key2);
    sendMoneyToWallet(wallet, AbstractBlockChain.NewBlockType.BEST_CHAIN, CENT, LegacyAddress.fromKey(UNITTEST, key1));
    sendMoneyToWallet(wallet, AbstractBlockChain.NewBlockType.BEST_CHAIN, CENT, LegacyAddress.fromKey(UNITTEST, key2));
    sendMoneyToWallet(wallet, AbstractBlockChain.NewBlockType.BEST_CHAIN, CENT, LegacyAddress.fromKey(UNITTEST, key2));
    Date compromiseTime = Utils.now();
    assertEquals(0, broadcaster.size());
    assertFalse(wallet.isKeyRotating(key1));

    // We got compromised!
    Utils.rollMockClock(1);
    wallet.setKeyRotationTime(compromiseTime);
    assertTrue(wallet.isKeyRotating(key1));
    wallet.doMaintenance(null, true);

    Transaction tx = broadcaster.waitForTransactionAndSucceed();
    final Coin THREE_CENTS = CENT.add(CENT).add(CENT);
    assertEquals(Coin.valueOf(49100), tx.getFee());
    assertEquals(THREE_CENTS, tx.getValueSentFromMe(wallet));
    assertEquals(THREE_CENTS.subtract(tx.getFee()), tx.getValueSentToMe(wallet));
    // TX sends to one of our addresses (for now we ignore married wallets).
    final Address toAddress = tx.getOutput(0).getScriptPubKey().getToAddress(UNITTEST);
    final ECKey rotatingToKey = wallet.findKeyFromPubHash(toAddress.getHash());
    assertNotNull(rotatingToKey);
    assertFalse(wallet.isKeyRotating(rotatingToKey));
    assertEquals(3, tx.getInputs().size());
    // It confirms.
    sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, tx);

    // Now receive some more money to the newly derived address via a new block and check that nothing happens.
    sendMoneyToWallet(wallet, AbstractBlockChain.NewBlockType.BEST_CHAIN, CENT, toAddress);
    assertTrue(wallet.doMaintenance(null, true).get().isEmpty());
    assertEquals(0, broadcaster.size());

    // Receive money via a new block on key1 and ensure it shows up as a maintenance task.
    sendMoneyToWallet(wallet, AbstractBlockChain.NewBlockType.BEST_CHAIN, CENT, LegacyAddress.fromKey(UNITTEST, key1));
    wallet.doMaintenance(null, true);
    tx = broadcaster.waitForTransactionAndSucceed();
    assertNotNull(wallet.findKeyFromPubHash(tx.getOutput(0).getScriptPubKey().getPubKeyHash()));
    log.info("Unexpected thing: {}", tx);
    assertEquals(Coin.valueOf(19300), tx.getFee());
    assertEquals(1, tx.getInputs().size());
    assertEquals(1, tx.getOutputs().size());
    assertEquals(CENT, tx.getValueSentFromMe(wallet));
    assertEquals(CENT.subtract(tx.getFee()), tx.getValueSentToMe(wallet));

    assertEquals(Transaction.Purpose.KEY_ROTATION, tx.getPurpose());

    // We don't attempt to race an attacker against unconfirmed transactions.

    // Now round-trip the wallet and check the protobufs are storing the data correctly.
    wallet = roundTrip(wallet);

    tx = wallet.getTransaction(tx.getHash());
    checkNotNull(tx);
    assertEquals(Transaction.Purpose.KEY_ROTATION, tx.getPurpose());
    // Have to divide here to avoid mismatch due to second-level precision in serialisation.
    assertEquals(compromiseTime.getTime() / 1000, wallet.getKeyRotationTime().getTime() / 1000);

    // Make a normal spend and check it's all ok.
    wallet.sendCoins(broadcaster, OTHER_ADDRESS, wallet.getBalance());
    tx = broadcaster.waitForTransaction();
    assertArrayEquals(OTHER_ADDRESS.getHash(), tx.getOutput(0).getScriptPubKey().getPubKeyHash());
}