mirror of
https://github.com/Rucknium/misc-research.git
synced 2024-12-22 11:29:22 +00:00
Add Mordinal/black marble analysis and plots
This commit is contained in:
parent
af0e084ba7
commit
8f84e9db52
2 changed files with 201 additions and 0 deletions
140
Monero-Effective-Ring-Size/analysis/black-marble-plots.R
Normal file
140
Monero-Effective-Ring-Size/analysis/black-marble-plots.R
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
# Must install:
|
||||||
|
# install.packages(c("data.table", "ggplot2", "scales"))
|
||||||
|
|
||||||
|
library(data.table)
|
||||||
|
library(ggplot2)
|
||||||
|
# Must also have scales package installed
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
p2pool.upgrade <- as.Date("2023-03-18")
|
||||||
|
first.mordinal <- as.Date("2023-03-10")
|
||||||
|
|
||||||
|
|
||||||
|
black.marble.share <- melt(black.marble.share, id.vars = "block_date", variable.factor = FALSE)
|
||||||
|
|
||||||
|
black.marble.share[grepl("mordinal", variable), variable := "Mordinal"]
|
||||||
|
black.marble.share[grepl("coinbase", variable), variable := "Coinbase"]
|
||||||
|
|
||||||
|
black.marble.share <- black.marble.share[block_date >= as.Date("2023-02-01"), ]
|
||||||
|
|
||||||
|
black.marble.share[variable == "Coinbase" & block_date < as.Date("2023-03-18"), mean(value)]
|
||||||
|
black.marble.share[variable == "Coinbase" & block_date > as.Date("2023-03-18"), mean(value)]
|
||||||
|
|
||||||
|
png("Monero-Effective-Ring-Size/analysis/images/mordinal-coinbase-output-share.png", width = 800, height = 800)
|
||||||
|
|
||||||
|
ggplot(black.marble.share) +
|
||||||
|
geom_line(aes(x = block_date, y = value, colour = variable), size = 1.5) +
|
||||||
|
ggtitle("Percentage of Monero Transaction Outputs That Are Mordinals and Coinbases") +
|
||||||
|
geom_vline( aes(xintercept = first.mordinal,
|
||||||
|
colour = "First Mordinal minted"), size = 1.5, linetype = 2, key_glyph = "rect") +
|
||||||
|
geom_vline( aes(xintercept = p2pool.upgrade,
|
||||||
|
colour = "P2Pool payout efficiency upgrade"), size = 1.5, linetype = 2, key_glyph = "rect") +
|
||||||
|
scale_colour_manual(name = NULL, aesthetics = c("colour", "fill"),
|
||||||
|
values = c("Mordinal" = "black", "Coinbase" = "darkgoldenrod2", "First Mordinal minted" = "khaki4",
|
||||||
|
"P2Pool payout efficiency upgrade" = "#FF6600FF")) +
|
||||||
|
xlab(" Date github.com/Rucknium") +
|
||||||
|
ylab("Share of Transaction Outputs") +
|
||||||
|
theme(plot.title = element_text(size = 20), legend.position = "top",
|
||||||
|
legend.text = element_text(size = 15),
|
||||||
|
axis.text = element_text(size = 15),
|
||||||
|
axis.title.x = element_text(size = 15, margin = margin(t = 10)),
|
||||||
|
axis.title.y = element_text(size = 15), strip.text = element_text(size = 15)) +
|
||||||
|
guides(colour = guide_legend(nrow = 2, byrow = TRUE)) +
|
||||||
|
geom_hline(aes(yintercept = 0), colour = "gray20") +
|
||||||
|
scale_y_continuous(labels = scales::percent_format(scale = 1),
|
||||||
|
breaks = seq(0, 100, by = 5), sec.axis = dup_axis(name = NULL))
|
||||||
|
|
||||||
|
dev.off()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
eff.ring.size.stats.mean <- eff.ring.size.stats[, .(block_timestamp_ring.time.date,
|
||||||
|
effective.ring.size.coinbase.mean, effective.ring.size.mordinal.mean,
|
||||||
|
effective.ring.size.coinbase.mordinal.mean )]
|
||||||
|
|
||||||
|
|
||||||
|
eff.ring.size.stats.mean <- melt(eff.ring.size.stats.mean,
|
||||||
|
id.vars = "block_timestamp_ring.time.date", variable.factor = FALSE)
|
||||||
|
|
||||||
|
eff.ring.size.stats.mean <- eff.ring.size.stats.mean[block_timestamp_ring.time.date >= as.Date("2023-02-01"), ]
|
||||||
|
|
||||||
|
eff.ring.size.stats.mean[grepl("coinbase.mordinal", variable), variable := "Combined Mordinal & Coinbase"]
|
||||||
|
eff.ring.size.stats.mean[grepl("mordinal", variable), variable := "Mordinal"]
|
||||||
|
eff.ring.size.stats.mean[grepl("coinbase", variable), variable := "Coinbase"]
|
||||||
|
|
||||||
|
|
||||||
|
png("Monero-Effective-Ring-Size/analysis/images/mean-effective-ring-size.png", width = 800, height = 800)
|
||||||
|
|
||||||
|
ggplot(eff.ring.size.stats.mean) +
|
||||||
|
geom_line(aes(x = block_timestamp_ring.time.date , y = value, colour = variable), size = 1.5) +
|
||||||
|
ggtitle("Average Empirical Effective Ring Size of Monero Transactions") +
|
||||||
|
geom_vline( aes(xintercept = first.mordinal,
|
||||||
|
colour = "First Mordinal"), size = 1.5, linetype = 2, key_glyph = "rect") +
|
||||||
|
geom_vline( aes(xintercept = p2pool.upgrade,
|
||||||
|
colour = "P2Pool payout efficiency upgrade"), size = 1.5, linetype = 2, key_glyph = "rect") +
|
||||||
|
scale_color_manual(name = NULL,
|
||||||
|
values = c("Mordinal" = "black", "Coinbase" = "darkgoldenrod1", "Combined Mordinal & Coinbase" = "purple",
|
||||||
|
"First Mordinal" = "khaki4", "P2Pool payout efficiency upgrade" = "#FF6600FF")) +
|
||||||
|
xlab(" Date github.com/Rucknium") +
|
||||||
|
ylab("Effective ring size (ring size minus number of Mordinal/coinbase outputs in the ring)") +
|
||||||
|
theme(plot.title = element_text(size = 20), legend.position = "top",
|
||||||
|
legend.text = element_text(size = 15),
|
||||||
|
axis.text = element_text(size = 15),
|
||||||
|
axis.title.x = element_text(size = 15, margin = margin(t = 10)),
|
||||||
|
axis.title.y = element_text(size = 15), strip.text = element_text(size = 15)) +
|
||||||
|
guides(colour = guide_legend(nrow = 2, byrow = TRUE)) +
|
||||||
|
scale_y_continuous(breaks = 0:100, sec.axis = dup_axis(name = NULL))
|
||||||
|
# Have an axis tick at every integer
|
||||||
|
|
||||||
|
dev.off()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
eff.ring.size.stats.5th.percentile <- eff.ring.size.stats[, .(block_timestamp_ring.time.date,
|
||||||
|
effective.ring.size.coinbase.percentile.05, effective.ring.size.mordinal.percentile.05,
|
||||||
|
effective.ring.size.coinbase.mordinal.percentile.05 )]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
eff.ring.size.stats.5th.percentile <- melt(eff.ring.size.stats.5th.percentile,
|
||||||
|
id.vars = "block_timestamp_ring.time.date", variable.factor = FALSE)
|
||||||
|
|
||||||
|
eff.ring.size.stats.5th.percentile <- eff.ring.size.stats.5th.percentile[
|
||||||
|
block_timestamp_ring.time.date >= as.Date("2023-02-01"), ]
|
||||||
|
|
||||||
|
eff.ring.size.stats.5th.percentile[grepl("coinbase.mordinal", variable), variable := "Combined Mordinal & Coinbase"]
|
||||||
|
eff.ring.size.stats.5th.percentile[grepl("mordinal", variable), variable := "Mordinal"]
|
||||||
|
eff.ring.size.stats.5th.percentile[grepl("coinbase", variable), variable := "Coinbase"]
|
||||||
|
|
||||||
|
|
||||||
|
png("Monero-Effective-Ring-Size/analysis/images/5th-percentile-effective-ring-size.png", width = 800, height = 800)
|
||||||
|
|
||||||
|
ggplot(eff.ring.size.stats.5th.percentile) +
|
||||||
|
geom_line(aes(x = block_timestamp_ring.time.date , y = value, colour = variable), size = 1.5) +
|
||||||
|
ggtitle('Empirical Effective Ring Size for the "Unluckiest" 5 Percent of Monero Rings\n(i.e. 5th Percentile of Empirical Effective Ring Size)') +
|
||||||
|
geom_vline( aes(xintercept = first.mordinal,
|
||||||
|
colour = "First Mordinal"), size = 1.5, linetype = 2, key_glyph = "rect") +
|
||||||
|
geom_vline( aes(xintercept = p2pool.upgrade,
|
||||||
|
colour = "P2Pool payout efficiency upgrade"), size = 1.5, linetype = 2, key_glyph = "rect") +
|
||||||
|
scale_color_manual(name = NULL,
|
||||||
|
values = c("Mordinal" = "black", "Coinbase" = "darkgoldenrod1", "Combined Mordinal & Coinbase" = "purple",
|
||||||
|
"First Mordinal" = "khaki4", "P2Pool payout efficiency upgrade" = "#FF6600FF")) +
|
||||||
|
xlab(" Date github.com/Rucknium") +
|
||||||
|
ylab("Effective ring size (ring size minus number of Mordinal/coinbase outputs in the ring)") +
|
||||||
|
theme(plot.title = element_text(size = 20), legend.position = "top",
|
||||||
|
legend.text = element_text(size = 15),
|
||||||
|
axis.text = element_text(size = 15),
|
||||||
|
axis.title.x = element_text(size = 15, margin = margin(t = 10)),
|
||||||
|
axis.title.y = element_text(size = 15), strip.text = element_text(size = 15)) +
|
||||||
|
guides(colour = guide_legend(nrow = 2, byrow = TRUE)) +
|
||||||
|
scale_y_continuous(breaks = 0:100, sec.axis = dup_axis(name = NULL))
|
||||||
|
# Have an axis tick at every integer
|
||||||
|
|
||||||
|
dev.off()
|
||||||
|
|
||||||
|
|
61
Monero-Effective-Ring-Size/black-marble-eff-ring-size.R
Normal file
61
Monero-Effective-Ring-Size/black-marble-eff-ring-size.R
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
# Must install:
|
||||||
|
# install.packages("data.table")
|
||||||
|
|
||||||
|
library(data.table)
|
||||||
|
|
||||||
|
|
||||||
|
black.marble.share <- output.index[, .(
|
||||||
|
coinbase.share = 100 * sum(tx_num == 1)/.N,
|
||||||
|
mordinal.share = 100 * sum(is_mordinal)/.N), by = "block_date"]
|
||||||
|
|
||||||
|
setorder(black.marble.share, block_date)
|
||||||
|
|
||||||
|
|
||||||
|
# Get number of Mordinals, fees paid, and tx size
|
||||||
|
output.index[is_mordinal & output_num == 1, .N]
|
||||||
|
|
||||||
|
output.index[is_mordinal & output_num == 1, sum(tx_fee) * 0.000000000001]
|
||||||
|
|
||||||
|
output.index[is_mordinal & output_num == 1, sum(tx_size_bytes)]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
eff.ring.size <- xmr.rings[, .(
|
||||||
|
n.coinbase.ring.members = sum(tx_num == 1), n.mordinal.ring.members = sum(is_mordinal), ring.size = .N),
|
||||||
|
by = c("tx_hash", "input_num", "block_timestamp_ring")]
|
||||||
|
|
||||||
|
eff.ring.size[, share.mordinal.ring.members := n.mordinal.ring.members/ring.size]
|
||||||
|
eff.ring.size[, effective.ring.size.coinbase := ring.size - n.coinbase.ring.members]
|
||||||
|
eff.ring.size[, effective.ring.size.mordinal := ring.size - n.mordinal.ring.members]
|
||||||
|
eff.ring.size[, effective.ring.size.coinbase.mordinal := ring.size - n.coinbase.ring.members - n.mordinal.ring.members]
|
||||||
|
eff.ring.size[, block_timestamp_ring.time := as.POSIXct(block_timestamp_ring, origin = "1970-01-01")]
|
||||||
|
|
||||||
|
eff.ring.size.date <- unique(eff.ring.size[, .(block_timestamp_ring.time = block_timestamp_ring.time)])
|
||||||
|
|
||||||
|
eff.ring.size.date[, block_timestamp_ring.time.isoweek :=
|
||||||
|
paste(lubridate::isoyear(block_timestamp_ring.time),
|
||||||
|
formatC(lubridate::isoweek(block_timestamp_ring.time), width = 2, flag = "0"), sep = "-")]
|
||||||
|
|
||||||
|
eff.ring.size.date[, block_timestamp_ring.time.date := as.Date(block_timestamp_ring.time)]
|
||||||
|
|
||||||
|
eff.ring.size <- merge(eff.ring.size, eff.ring.size.date)
|
||||||
|
# speed improvement by splitting and then merging
|
||||||
|
|
||||||
|
setorder(eff.ring.size, block_timestamp_ring.time.date)
|
||||||
|
|
||||||
|
|
||||||
|
eff.ring.size.stats <- eff.ring.size[, .(
|
||||||
|
effective.ring.size.coinbase.mean = as.numeric(mean(effective.ring.size.coinbase)),
|
||||||
|
effective.ring.size.coinbase.median = as.numeric(median(effective.ring.size.coinbase)),
|
||||||
|
effective.ring.size.coinbase.percentile.05 = as.numeric(quantile(effective.ring.size.coinbase, probs = 0.05)),
|
||||||
|
effective.ring.size.mordinal.mean = as.numeric(mean(effective.ring.size.mordinal)),
|
||||||
|
effective.ring.size.mordinal.median = as.numeric(median(effective.ring.size.mordinal)),
|
||||||
|
effective.ring.size.mordinal.percentile.05 = as.numeric(quantile(effective.ring.size.mordinal, probs = 0.05)),
|
||||||
|
effective.ring.size.coinbase.mordinal.mean = as.numeric(mean(effective.ring.size.coinbase.mordinal)),
|
||||||
|
effective.ring.size.coinbase.mordinal.median = as.numeric(median(effective.ring.size.coinbase.mordinal)),
|
||||||
|
effective.ring.size.coinbase.mordinal.percentile.05 = as.numeric(quantile(effective.ring.size.coinbase.mordinal, probs = 0.05))
|
||||||
|
# as.numeric() to make sure results of each "by" subset are all floats
|
||||||
|
), by = "block_timestamp_ring.time.date"]
|
||||||
|
|
||||||
|
|
||||||
|
setorder(eff.ring.size.stats, block_timestamp_ring.time.date)
|
Loading…
Reference in a new issue