Below is a table of the attack success probability for different values of the adversary's hashpower share and the number of blocks that the victim waits for "full confirmation" of a transaction.
The computations are based on Theorem 1 of Grunspan & Perez-Marco (2018). "Double spend races." It is assumed that the attacker has a one-block advantage at the start of the attack.
Theorem 1 is
Let
where
See https://miningpoolstats.stream/monero for current hashpower share of the major mining pools.
Columns are the hashpower share of the adversary. Rows are the number of mined blocks that the victim waits before considering a transaction "confirmed".
0.05 | 0.1 | 0.2 | 0.3 | 0.4 | 0.45 | |
---|---|---|---|---|---|---|
1 | 10.00000 | 20.00000 | 40.00000 | 60.00000 | 80.00000 | 90.00000 |
2 | 1.45000 | 5.60000 | 20.80000 | 43.20000 | 70.40000 | 85.05000 |
3 | 0.23162 | 1.71200 | 11.58400 | 32.61600 | 63.48800 | 81.37463 |
4 | 0.03872 | 0.54560 | 6.66880 | 25.20720 | 57.95840 | 78.34244 |
5 | 0.00664 | 0.17818 | 3.91629 | 19.76173 | 53.31354 | 75.71581 |
6 | 0.00116 | 0.05914 | 2.33084 | 15.64496 | 49.30037 | 73.37548 |
7 | 0.00021 | 0.01986 | 1.40071 | 12.47504 | 45.76879 | 71.25164 |
8 | 0.00004 | 0.00672 | 0.84795 | 10.00251 | 42.62064 | 69.29921 |
9 | 0.00001 | 0.00229 | 0.51629 | 8.05539 | 39.78730 | 67.48712 |
10 | 0.00000 | 0.00079 | 0.31582 | 6.51067 | 37.21840 | 65.79282 |
11 | 0.00000 | 0.00027 | 0.19394 | 5.27799 | 34.87557 | 64.19932 |
12 | 0.00000 | 0.00009 | 0.11948 | 4.28960 | 32.72869 | 62.69347 |
13 | 0.00000 | 0.00003 | 0.07381 | 3.49395 | 30.75355 | 61.26479 |
14 | 0.00000 | 0.00001 | 0.04571 | 2.85131 | 28.93035 | 59.90480 |
15 | 0.00000 | 0.00000 | 0.02836 | 2.33077 | 27.24259 | 58.60650 |
16 | 0.00000 | 0.00000 | 0.01763 | 1.90809 | 25.67635 | 57.36402 |
17 | 0.00000 | 0.00000 | 0.01098 | 1.56413 | 24.21974 | 56.17240 |
18 | 0.00000 | 0.00000 | 0.00685 | 1.28371 | 22.86252 | 55.02740 |
19 | 0.00000 | 0.00000 | 0.00427 | 1.05470 | 21.59579 | 53.92534 |
20 | 0.00000 | 0.00000 | 0.00267 | 0.86739 | 20.41173 | 52.86301 |
21 | 0.00000 | 0.00000 | 0.00167 | 0.71398 | 19.30344 | 51.83759 |
22 | 0.00000 | 0.00000 | 0.00105 | 0.58819 | 18.26482 | 50.84660 |
23 | 0.00000 | 0.00000 | 0.00066 | 0.48492 | 17.29041 | 49.88782 |
24 | 0.00000 | 0.00000 | 0.00041 | 0.40007 | 16.37531 | 48.95926 |
25 | 0.00000 | 0.00000 | 0.00026 | 0.33027 | 15.51511 | 48.05913 |
26 | 0.00000 | 0.00000 | 0.00016 | 0.27282 | 14.70584 | 47.18583 |
27 | 0.00000 | 0.00000 | 0.00010 | 0.22548 | 13.94388 | 46.33789 |
28 | 0.00000 | 0.00000 | 0.00006 | 0.18646 | 13.22594 | 45.51397 |
29 | 0.00000 | 0.00000 | 0.00004 | 0.15427 | 12.54903 | 44.71286 |
30 | 0.00000 | 0.00000 | 0.00003 | 0.12769 | 11.91040 | 43.93344 |
R code to reproduce the table:
# install.packages("zipfR")
# install.packages("knitr")
# Rows: 1 to 30 number of blocks to wait
# Column: hashpower share: 5%, 10%, 20%, 30%, 40%, 45%
# Based on Theorem 1 of Grunspan & Perez-Marco (2018). "Double spend races."
n.blocks <- 30
hashpower.share <- c(0.05, 0.10, 0.20, 0.30, 0.40, 0.45)
blocks <- 1:n.blocks
results <- matrix(0, nrow = n.blocks, ncol = length(hashpower.share))
for (i in seq_along(hashpower.share)) {
q = hashpower.share[i]
p = 1 - q
results[, i] <- zipfR::Rbeta(x = 4*p*q, a = blocks, b = 1/2)
}
results <- 100 * results # Convert to percentage
rownames(results) <- as.character(blocks)
comparison.block <- 10
results.comparison <- results
for (j in seq_len(ncol(results.comparison))) {
divisor <- results[blocks == comparison.block, j]
results.comparison[, j] <- results.comparison[, j] / divisor
}
knitr::kable(results, format = "pipe", row.names = TRUE,
col.names = hashpower.share, digits = 5)