• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

bernardladenthin / BitcoinAddressFinder / #327

06 Jun 2025 10:36PM UTC coverage: 65.407% (-0.7%) from 66.078%
#327

push

bernardladenthin
refactor: simplify Bech32 detection and fallback, add tests for invalid addresses

4 of 4 new or added lines in 1 file covered. (100.0%)

8 existing lines in 3 files now uncovered.

1246 of 1905 relevant lines covered (65.41%)

0.65 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.79
/src/main/java/net/ladenthin/bitcoinaddressfinder/AddressFilesToLMDB.java
1
// @formatter:off
2
/**
3
 * Copyright 2020 Bernard Ladenthin bernard.ladenthin@gmail.com
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 *    http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 */
18
// @formatter:on
19
package net.ladenthin.bitcoinaddressfinder;
20

21
import net.ladenthin.bitcoinaddressfinder.persistence.PersistenceUtils;
22
import org.slf4j.Logger;
23
import org.slf4j.LoggerFactory;
24

25
import java.io.File;
26
import java.io.IOException;
27
import java.nio.ByteBuffer;
28
import java.util.List;
29
import java.util.concurrent.atomic.AtomicBoolean;
30
import java.util.concurrent.atomic.AtomicLong;
31
import java.util.concurrent.atomic.AtomicReference;
32
import net.ladenthin.bitcoinaddressfinder.configuration.CAddressFilesToLMDB;
33
import net.ladenthin.bitcoinaddressfinder.persistence.lmdb.LMDBPersistence;
34
import org.bitcoinj.base.Network;
35
import org.jspecify.annotations.NonNull;
36

37
public class AddressFilesToLMDB implements Runnable, Interruptable {
38
    
39
    private final static long PROGRESS_LOG = 100_000;
40

41
    private final Logger logger = LoggerFactory.getLogger(AddressFilesToLMDB.class);
1✔
42

43
    private final CAddressFilesToLMDB addressFilesToLMDB;
44

45
    private LMDBPersistence persistence;
46

47
    private final AtomicLong addressCounter = new AtomicLong();
1✔
48

49
    private final ReadStatistic readStatistic = new ReadStatistic();
1✔
50

51
    @NonNull
1✔
52
    AtomicReference<AddressFile> currentAddressFile = new AtomicReference<>();
53
    
54
    protected final AtomicBoolean shouldRun = new AtomicBoolean(true);
1✔
55
    
56
    public AddressFilesToLMDB(CAddressFilesToLMDB addressFilesToLMDB) {
1✔
57
        this.addressFilesToLMDB = addressFilesToLMDB;
1✔
58
    }
1✔
59

60
    @Override
61
    public void run() {
62
        final Network network = new NetworkParameterFactory().getNetwork();
1✔
63

64
        PersistenceUtils persistenceUtils = new PersistenceUtils(network);
1✔
65
        persistence = new LMDBPersistence(addressFilesToLMDB.lmdbConfigurationWrite, persistenceUtils);
1✔
66
        logger.info("Init LMDB ...");
1✔
67
        persistence.init();
1✔
68
        logger.info("... init LMDB done.");
1✔
69

70
        try {
71
            FileHelper fileHelper = new FileHelper();
1✔
72
            List<File> files = fileHelper.stringsToFiles(addressFilesToLMDB.addressesFiles);
1✔
73
            fileHelper.assertFilesExists(files);
1✔
74
            
75
            logger.info("Iterate address files ...");
1✔
76
            for (File file : files) {
1✔
77
                if (!shouldRun.get()) {
1✔
78
                    break;
×
79
                }
80
                AddressFile addressFile = new AddressFile(
1✔
81
                    file,
82
                    readStatistic,
83
                    network,
84
                    this::supported,
85
                    this::unsupported
86
                );
87
                
88
                logger.info("process " + file.getAbsolutePath());
1✔
89
                currentAddressFile.set(addressFile);
1✔
90
                addressFile.readFile();
1✔
91
                currentAddressFile.set(null);
1✔
92
                logger.info("finished: " + file.getAbsolutePath());
1✔
93
                
94
                logProgress();
1✔
95
            }
1✔
96
            logProgress();
1✔
97
            logger.info("... iterate address files done.");
1✔
98

99
            for (String error : readStatistic.errors) {
1✔
UNCOV
100
                logger.info("Error in line: " + error);
×
UNCOV
101
            }
×
102
        } catch (IOException e) {
×
103
            throw new RuntimeException(e);
×
104
        } finally {
105
            persistence.close();
1✔
106
        }
107
    }
1✔
108
    
109
    private void supported(AddressToCoin addressToCoin) {
110
        ByteBuffer hash160 = addressToCoin.hash160();
1✔
111
        persistence.putNewAmount(hash160, addressToCoin.coin());
1✔
112
        addressCounter.incrementAndGet();
1✔
113

114
        if (addressCounter.get() % PROGRESS_LOG == 0) {
1✔
115
            logProgress();
×
116
        }
117
    }
1✔
118

119
    private void unsupported(String line) {
120
        if (readStatistic.unsupported % PROGRESS_LOG == 0) {
1✔
121
            logProgress();
1✔
122
        }
123
    }
1✔
124

125
    private void logProgress() {
126
        logger.info("Progress: " + addressCounter.get() + " addresses. Unsupported: " + readStatistic.unsupported + ". Errors: " + readStatistic.errors.size() + ". Current File progress: " + String.format("%.2f", readStatistic.currentFileProgress) + "%.");
1✔
127
    }
1✔
128

129
    @Override
130
    public void interrupt() {
131
        AddressFile addressFile = currentAddressFile.get();
1✔
132
        if (addressFile != null) {
1✔
133
            addressFile.interrupt();
×
134
        }
135
    }
1✔
136
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc