Mar 16, 2021 • Graham Higgins • ~ 11 min to read •
Q. Why does specifying a shift of 25 result in the miner using an 85-digit prime?
A. (From J0nn9) “256 + shift
is the bit size of the prime you are searching for. The shift size
has to be greater than 13.”
In using the phrase “the bit size of the prime”, he is referencing bits and bytes of information.
One “bit” of information is 0 or 1. This is the smallest piece of storable information. “bit” is short for ”binary digit” and can store two states: off or on, 0 or 1, false or true.
One “byte” of information is defined as 8 bits. So 256 bits is 32 bytes in the same way that 2500 millimeters is 2.5 meters. A byte can represent any combination of 0s and 1s between 00000000 and 11111111 and all stations in-between e.g. 00001111, 10101010, 01010101, 00110100.
This combination can be more readably expressed in hexadecimal. 0x00 (0 in decimal) represents 00000000, 0xff (256 in decimal) represents 11111111 and, as examples of the stations in-between: 0xf0 (240 in decimal) represents 11110000 and 0x0f (16 in decimal) represents 00001111.
(I’m following standard practice by denoting a hexadecimal representation by the leading pair of “0x” characters)
So the 256 bits of the “bit size of the prime” would be written out in full as:
000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000
or
111111111111111111111111111111111111111111111111111111111111111111111111111111
111111111111111111111111111111111111111111111111111111111111111111111111111111
111111111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111
and (just one example of) all stations in-between:
010101010101010101010101010101010101010101010101010101010101010101010101010101
010101010101010101010101010101010101010101010101010101010101010101010101010101
010101010101010101010101010101010101010101010101010101010101010101010101010101
0101010101010101010101
The same 256 bits expressed in hexadecimal representation is less unwieldy.
0x0000000000000000000000000000000000000000000000000000000000000000
or
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
and stations in-between
0xf8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8
And so the hexadecimal representation is generally preferred — and supported so I’ll be using for preference in the next section of this explainer
…
You’ll likely be aware that digital computers use bits (0s and 1s) to represent numbers.
The Python programming language offers a readable way of playing with bits, bytes and numerical representations, including hexadecimal.
If I feed my Python interpreter with a hexadecimal number, it tells me what that number is in decimal.
I can feed it the hexadecimal for 256 bits, all set to 1:
>>> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
115792089237316195423570985008687907853269984665640564039457584007913129639935
And I can ask it how many digits are in that decimal number:
>>> len("115792089237316195423570985008687907853269984665640564039457584007913129639935")
78
Given J0nn9’s reply of “256 + shift
is the bit size of the prime” …
We can try this with a shift of 25, making the bit size 256 + 25 which totals 281.
281 bits expressed in hexadecmal is:
0x00000000000000000000000000000000000000000000000000000000000000000000000
(as opposed to the 256 bits of):
0x0000000000000000000000000000000000000000000000000000000000000000
Python’s quite good for throwing numbers around. It can readily turn sequences of strings of “1”s and “0”s into numbers.
Here’s an example of it printing out the decimal representation of the byte
11111111
(hexadecimal 0xff
):
>> print(int('11111111', 2)) # parse the string '11111111' as an integer with base 2
255
>>> print(hex(int('11111111', 2)))
0xff
Handily, Python has a shorthand that allows one to print a string several times, e.g. 32 “1”s:
>>> print("1"*32)
11111111111111111111111111111111
This shorthand can be used with the previous explict bit string of ‘11111111’ (eight “1”s)
>>> print(int('1'*8, 2))
255
Now, we we can use this shorthand to print out the new bit size of 281 “1”s
>> print(int('1'*281, 2))
3885337784451458141838923813647037813284813678104279042503624819477808570410416996351
So, how many digits in that number?
>>> len("3885337784451458141838923813647037813284813678104279042503624819477808570410416996351")
85
And there you have the numbers that lie behind J0nn9’s statement:
“`256 + shift` is the bit size of the prime you are searching for”
Using a shift of 25 means a bit size of 256 + 25 (= 281) which results in Gapcoin searching for gaps between 85-digit primes.
To find the length of the prime for a specific shift, we can use a variable.
Rather than the usual but cryptic x
, we can use a more descriptive variable name: SHIFT
…
print(len(str(int('1'*(256+SHIFT),2))))
And by assigning different values to SHIFT
, we can get a sense of its
impact on the length of the primes to be searched.
. . .
A shift of 25 will result in primes with 85 digits
>>> SHIFT = 25
>>> print(len(str(int('1'*(256+SHIFT),2))))
85
A shift of 128 will result in primes with 116 digits
>>> SHIFT = 128
>>> print(len(str(int('1'*(256+SHIFT),2))))
116
The allowed minimum shift of 13 results in 81-digit primes
>>> SHIFT = 13
>>> print(len(str(int('1'*(256+SHIFT),2))))
81
The default shift of 25 (as encoded in the Gapcoin C++ source and in the GapMiner source) results in 85-digit primes
>>> SHIFT = 25
>>> print(len(str(int('1'*(256+SHIFT),2))))
85
(So by default Gapcoin searches for gaps between 85-digit primes and that is why there’s such a strong concentration of Gapcoin-discovered gaps in Seth Troisi’s end-of-2020 graph of prime-length vs gap coverage.)
Back in 2014, J0nn9 observed: “shift can theoretically be in range [14, 2^16]
,
but nodes can choose to only accept shifts till a given amount (e.g. 512 for the
main nodes)”
However, this upper limit of 512 was later increased to 1024.
>>> SHIFT = 1024
>>> print(len(str(int('1'*(256+SHIFT),2))))
386
A 386-digit prime is quite a large number:
1983423893055277343771839442553463759456121569397634422513819961
1507538399093415101489223407213551698761866068732737252027269776
7154619951173536174717936999718490306477336080747887166904476954
8319471533223333475285033669837852384808841224768815857595158432
1880080025074484205788751028980294739160978233965869789764051556
5099862840015057267339368918911954021678927068721903471912239965
89
According to wikipedia¹, a septillion is only 25 digits long.
Even a Millinillion² at 10^3003 is “only” 3004 digits in length:
>> pow(10, 3003)
100000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000
Using the maximum shift of 2^16 gets you into the serious territory of primes with nearly 20,000 digits, waaay bigger even than millinillions (millinillimillinillinillions?)
>>> SHIFT = pow(2, 16)
>>> print(len(str(int('1'*(256+SHIFT),2))))
19806
Primes of this length aren’t suitable for using as the basis of a Proof-Of-Work algorithm for a cryptocurrency because the computational work of just checking the PoW of such a large prime may well act as a denial-of-service attack on the chain.
Below is a small Python routine that shows the corresponding prime lengths for each of the shifts:
>>> [len(str(int('1'*(256+SHIFT),2))) for SHIFT in range(15, 155, 10)]
[82, 85, 88, 91, 94, 97, 100, 103, 106, 109, 112, 115, 118, 121]
The example below is the result of a couple of limited tests of the Gapcoin cpuminer running on a Dell XPS 9569 i7 laptop at shifts of 32 and 64 with the default sieve-size and sieve-primes settings:
--threads 1 --shift 32 --sieve-size 33554432 --sieve-primes 900000 -j 5 -e
[2021-03-19 14:21:32] pps: 219195 / 219631 tests/s 69867 / 70749 gaps/s 10378 / 10405
[2021-03-19 14:21:37] pps: 216931 / 219515 tests/s 70140 / 70821 gaps/s 10278 / 10400
[2021-03-19 14:21:42] pps: 220776 / 214989 tests/s 71526 / 69464 gaps/s 10460 / 10185
[2021-03-19 14:21:47] pps: 215538 / 215627 tests/s 69858 / 69744 gaps/s 10213 / 10216
[2021-03-19 14:21:52] pps: 221439 / 215644 tests/s 71773 / 69772 gaps/s 10493 / 10217
[2021-03-19 14:21:57] pps: 217258 / 215948 tests/s 69879 / 69817 gaps/s 10289 / 10231
[2021-03-19 14:22:02] pps: 218976 / 216395 tests/s 70417 / 69922 gaps/s 10373 / 10252
[2021-03-19 14:22:07] pps: 218754 / 216557 tests/s 71559 / 69962 gaps/s 10369 / 10260
[2021-03-19 14:22:12] pps: 221418 / 216953 tests/s 70514 / 70076 gaps/s 10482 / 10278
[2021-03-19 14:22:17] pps: 224622 / 217301 tests/s 72134 / 70189 gaps/s 10639 / 10295
[2021-03-19 14:22:22] pps: 220063 / 217468 tests/s 70087 / 70237 gaps/s 10418 / 10303
[2021-03-19 14:22:27] pps: 219848 / 217685 tests/s 71645 / 70293 gaps/s 10420 / 10313
[2021-03-19 14:22:32] pps: 219698 / 217660 tests/s 71050 / 70293 gaps/s 10408 / 10312
[2021-03-19 14:22:37] pps: 213912 / 217468 tests/s 68960 / 70231 gaps/s 10130 / 10303
--threads 1 --shift 64 --sieve-size 33554432 --sieve-primes 900000 -j 5 -e
[2021-03-19 14:20:03] pps: 166291 / 169551 tests/s 60031 / 60985 gaps/s 7879 / 8032
[2021-03-19 14:20:08] pps: 165653 / 170272 tests/s 59199 / 60846 gaps/s 7846 / 8065
[2021-03-19 14:20:13] pps: 168338 / 166193 tests/s 60731 / 59428 gaps/s 7977 / 7873
[2021-03-19 14:20:18] pps: 172167 / 168326 tests/s 61802 / 60242 gaps/s 8157 / 7975
[2021-03-19 14:20:23] pps: 177640 / 168989 tests/s 63981 / 60495 gaps/s 8422 / 8006
[2021-03-19 14:20:28] pps: 170073 / 169990 tests/s 60453 / 60750 gaps/s 8057 / 8054
[2021-03-19 14:20:33] pps: 168925 / 170474 tests/s 60395 / 60966 gaps/s 8004 / 8077
[2021-03-19 14:20:38] pps: 172555 / 168662 tests/s 61492 / 60348 gaps/s 8173 / 7991
[2021-03-19 14:20:43] pps: 179819 / 169214 tests/s 63995 / 60563 gaps/s 8519 / 8018
[2021-03-19 14:20:48] pps: 181478 / 169949 tests/s 64944 / 60849 gaps/s 8599 / 8053
[2021-03-19 14:20:53] pps: 178819 / 170347 tests/s 64278 / 60963 gaps/s 8475 / 8072
[2021-03-19 14:20:58] pps: 177222 / 170397 tests/s 62913 / 60981 gaps/s 8393 / 8074
[2021-03-19 14:21:03] pps: 170860 / 170240 tests/s 62286 / 60969 gaps/s 8103 / 8067
¹ Wikpedia Names of large numbers
² Stewart, Ian (2017). Infinity: A Very Short Introduction (illustrated ed.). Oxford University Press. p. 20. Extract of Page 20