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

bernardladenthin / BitcoinAddressFinder / #307

26 Apr 2025 08:18PM UTC coverage: 68.832% (+0.4%) from 68.475%
#307

push

bernardladenthin
Rewrite OpenCL result parsing (X/Y split), add clean shutdown, optimize runtime key validation

16 of 29 new or added lines in 5 files covered. (55.17%)

1 existing line in 1 file now uncovered.

1208 of 1755 relevant lines covered (68.83%)

0.69 hits per line

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

0.0
/src/main/java/net/ladenthin/bitcoinaddressfinder/OpenCLGridResult.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 java.math.BigInteger;
22
import java.nio.ByteBuffer;
23
import net.ladenthin.bitcoinaddressfinder.configuration.CConsumerJava;
24

25
public class OpenCLGridResult {
26
    
27
    /**
28
     * Enable additional validation to check if generated uncompressed keys are not all zero.
29
     * <p>
30
     * This should remain <b>disabled in production</b> to avoid unnecessary performance overhead.
31
     * Useful only during debugging or when validating OpenCL/GPU kernel correctness.
32
     * </p>
33
     * <p>
34
     * Superseded by {@link PublicKeyBytes#runtimePublicKeyCalculationCheck(org.slf4j.Logger)}
35
     * and its activation via {@link CConsumerJava#runtimePublicKeyCalculationCheck}.
36
     * </p>
37
     */
38
    private static final boolean ENABLE_UNCOMPRESSED_KEY_VALIDATION = false;
39

40
    private final ByteBufferUtility byteBufferUtility = new ByteBufferUtility(true);
×
41
    
42
    private final BigInteger secretKeyBase;
43
    private final int workSize;
44
    private ByteBuffer result;
45
    
46
    OpenCLGridResult(BigInteger secretKeyBase, int workSize, ByteBuffer result) {
×
47
        this.secretKeyBase = secretKeyBase;
×
48
        this.workSize = workSize;
×
49
        this.result = result;
×
50
    }
×
51

52
    public BigInteger getSecretKeyBase() {
53
        return secretKeyBase;
×
54
    }
55

56
    public int getWorkSize() {
57
        return workSize;
×
58
    }
59

60
    public ByteBuffer getResult() {
61
        return result;
×
62
    }
63
    
64
    public void freeResult() {
65
        // free and do not use anymore
66
        byteBufferUtility.freeByteBuffer(result);
×
67
        result = null;
×
68
    }
×
69
    
70
    /**
71
     * Time consuming.
72
     */
73
    public PublicKeyBytes[] getPublicKeyBytes() {
74
        PublicKeyBytes[] publicKeys = new PublicKeyBytes[workSize];
×
75
        for (int i = 0; i < workSize; i++) {
×
76
            PublicKeyBytes publicKeyBytes = getPublicKeyFromByteBufferXY(result, i, secretKeyBase);
×
77
            publicKeys[i] = publicKeyBytes;
×
78
        }
79
        return publicKeys;
×
80
    }
81
    
82
    /**
83
     * Read the inner bytes in reverse order.
84
     */
85
    private static final PublicKeyBytes getPublicKeyFromByteBufferXY(ByteBuffer b, int keyNumber, BigInteger secretKeyBase) {
86
        BigInteger secret = AbstractProducer.calculateSecretKey(secretKeyBase, keyNumber);
×
87
        if(BigInteger.ZERO.equals(secret)) {
×
88
            // the calculated key is invalid, return a fallback
89
            return PublicKeyBytes.INVALID_KEY_ONE;
×
90
        }
NEW
91
        final int resultBlockSize = PublicKeyBytes.TWO_COORDINATES_NUM_BYTES;
×
NEW
92
        final int keyOffsetInByteBuffer = resultBlockSize*keyNumber;
×
93
        
94
        // Read XY block
NEW
95
        byte[] kernelResultBlock = new byte[resultBlockSize];
×
NEW
96
        b.get(keyOffsetInByteBuffer, kernelResultBlock, 0, resultBlockSize);
×
97
        
98
        // Extract and reverse X
NEW
99
        byte[] x = new byte[PublicKeyBytes.ONE_COORDINATE_NUM_BYTES];
×
NEW
100
        System.arraycopy(kernelResultBlock, 0, x, 0, PublicKeyBytes.ONE_COORDINATE_NUM_BYTES);
×
101
        // LSB to MSB: From Java to OpenCL
NEW
102
        ByteBufferUtility.reverse(x);
×
103
        
104
        // Extract and reverse Y
NEW
105
        byte[] y = new byte[PublicKeyBytes.ONE_COORDINATE_NUM_BYTES];
×
NEW
106
        System.arraycopy(kernelResultBlock, PublicKeyBytes.ONE_COORDINATE_NUM_BYTES, y, 0, PublicKeyBytes.ONE_COORDINATE_NUM_BYTES);
×
107
        // LSB to MSB: From Java to OpenCL
NEW
108
        ByteBufferUtility.reverse(y);
×
109
        
110
        // Assemble uncompressed key
NEW
111
        byte[] uncompressed = PublicKeyBytes.assembleUncompressedPublicKey(x,y);
×
112
        
113
        if (ENABLE_UNCOMPRESSED_KEY_VALIDATION) {
114
            boolean allZero = PublicKeyBytes.isAllCoordinateBytesZero(uncompressed);
115
            if (allZero) {
116
                throw new RuntimeException("Invalid GPU result: all coordinate bytes are zero in uncompressed public key.");
117
            }
118
        }
119
        PublicKeyBytes publicKeyBytes = new PublicKeyBytes(secret, uncompressed);
×
120
        return publicKeyBytes;
×
121
    }
122
}
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