mirror of
				https://github.com/Qortal/altcoinj.git
				synced 2025-11-03 05:57:21 +00:00 
			
		
		
		
	Key rotation: fix bug that could cause multiple identical key chains to be created over and over if the key rotation time was equal to the time of the oldest best key, with test coverage.
This commit is contained in:
		
				
					committed by
					
						
						Andreas Schildbach
					
				
			
			
				
	
			
			
			
						parent
						
							23b3a637ab
						
					
				
				
					commit
					146f082dfb
				
			@@ -4391,7 +4391,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
 | 
			
		||||
        // We might have to create a new HD hierarchy if the previous ones are now rotating.
 | 
			
		||||
        boolean allChainsRotating = true;
 | 
			
		||||
        for (DeterministicKeyChain chain : keychain.getDeterministicKeyChains()) {
 | 
			
		||||
            if (chain.getEarliestKeyCreationTime() > vKeyRotationTimestamp) {
 | 
			
		||||
            if (chain.getEarliestKeyCreationTime() >= vKeyRotationTimestamp) {
 | 
			
		||||
                allChainsRotating = false;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -67,7 +67,7 @@ public class KeyChainGroup implements KeyBag {
 | 
			
		||||
 | 
			
		||||
    private BasicKeyChain basic;
 | 
			
		||||
    private NetworkParameters params;
 | 
			
		||||
    private final List<DeterministicKeyChain> chains;
 | 
			
		||||
    protected final List<DeterministicKeyChain> chains;
 | 
			
		||||
    private final EnumMap<KeyChain.KeyPurpose, DeterministicKey> currentKeys;
 | 
			
		||||
 | 
			
		||||
    // The map keys are the watching keys of the followed chains and values are the following chains
 | 
			
		||||
 
 | 
			
		||||
@@ -52,6 +52,7 @@ import java.util.concurrent.CountDownLatch;
 | 
			
		||||
import java.util.concurrent.TimeUnit;
 | 
			
		||||
import java.util.concurrent.atomic.AtomicBoolean;
 | 
			
		||||
import java.util.concurrent.atomic.AtomicInteger;
 | 
			
		||||
import java.util.concurrent.atomic.AtomicReference;
 | 
			
		||||
 | 
			
		||||
import static org.bitcoinj.core.Coin.*;
 | 
			
		||||
import static org.bitcoinj.core.Utils.HEX;
 | 
			
		||||
@@ -2393,10 +2394,17 @@ public class WalletTest extends TestWithWallet {
 | 
			
		||||
        goodKey.setCreationTimeSeconds(Utils.currentTimeSeconds());
 | 
			
		||||
 | 
			
		||||
        // Do an upgrade based on the bad key.
 | 
			
		||||
        KeyChainGroup kcg = new KeyChainGroup(params);
 | 
			
		||||
        final AtomicReference<List<DeterministicKeyChain>> fChains = new AtomicReference<List<DeterministicKeyChain>>();
 | 
			
		||||
        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());
 | 
			
		||||
@@ -2411,6 +2419,17 @@ public class WalletTest extends TestWithWallet {
 | 
			
		||||
        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());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test(expected = IllegalArgumentException.class)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user