Posted on Leave a comment

Exportación de los UTXO de Bitcoin a una base de datos

utxo Bitcoin

Los UTXO (Unspent Transaction Output) son las transacciones en las cuales las salidas no han sido gastadas es decir enviadas a otra dirección. Una transacción en Bitcoin está compuesta por una o varias direcciones de entrada con BTC/satoshis y una o varias direcciones de salida donde acaban los fondos, si estos BTC no han sido enviados en otra transacción posterior a otra dirección se la denomina UTXO. La suma de todos los fondos que hay en las direcciones de salida de las UTXO suman el total de monedas que hay. En Bitcoin existe una base de datos denominada chainstate que contiene únicamente esas transacciones y que se utiliza para evitar tener que realizar ciertas búsquedas sobre toda la Blockchain. 

Para guardar estos UTXO se utiliza el software LevelDB que es un almacenamiento clave-valor de muy rápida lectura y escritura desarrollada por Google que proporciona una asignación ordenada de claves y valores.

Greg Walker ha implementado la utilidad bitcoin-utxo-dump para exportar las UTXO a un fichero de texto, para ello se basó en las bitcoin tools de Sergi Delgado Segura, aquí vamos a utilizar la herramienta de in3rsha para crear un script que haga el dump de todos los UTXO a una base de datos PostgreSQL. Gracias a ello podemos realizar cualquier consulta sobre los UTXO con las facilidades que nos provee una base de datos relacional.

Una vez exportadas transacciones aprovecharemos para lanzar unas consultas sobre la tabla utxo generada para saber cuántas direcciones hay con más de 0,00001, 0,1, 1 y 1000 BTC. Si nos interesase tener estos datos diariamente, por ejemplo para conocer la evolución del número de ballenas (>= 1000BTC), sólo tendríamos que crear un job en linux para ejecutar el script diariamente.

https://github.com/BGeometrics/bitcoin-utils/blob/master/scripts/utxo2ddbb.sh

#!/bin/bash

# Script to dump bitcoin utxo database to postgres database
 
# Install go and postgreSQL
#### apt install golang postgresql
# Stop bitcoin full node because two applications cannot access LevelDB at the same time
# Access user postgres
#### sudo su - postgres
# Create directory for GOPATH
#### mkdir $HOME/go
#### export GOPATH="$HOME/go/"

DIR_CHAINSTATE=/mnt/hgfs/Proyect/bitcoin-utxo-dump/chainstate
DIR_DUMP=/mnt/hgfs/Proyect/bitcoin-utxo-dump/
PGPASSWORD=postgres
 
# Download and compile program bitcoin-utxo-dump of ins3rsha
go get github.com/in3rsha/bitcoin-utxo-dump

# Execure dump Bitcoin utxo to file
./go/bin/bitcoin-utxo-dump -db $DIR_CHAINSTATE

# Import dump in table in database
psql -d postgres -U postgres -c "DROP INDEX IF EXISTS index_address_amount;"
psql -d postgres -U postgres -c "DROP TABLE IF EXISTS utxo;"
psql -d postgres -U postgres -c "CREATE TABLE IF NOT EXISTS utxo (id INT NOT NULL, tx_id VARCHAR(100) NOT NULL, vout INT NOT NULL, amount BIGINT NOT NULL, type VARCHAR(50) NOT NULL, address VARCHAR(100));"
psql -d postgres -U postgres -c "copy utxo(id, tx_id, vout, amount, type, address) FROM '$DIR_DUMP/utxodump.csv'  DELIMITER ',' CSV HEADER;"
psql -d postgres -U postgres -c "CREATE INDEX IF NOT EXISTS index_address_amount ON utxo (address, amount);"
psql -d postgres -U postgres -c "CREATE TABLE IF NOT EXISTS address (THE_DATE DATE NOT NULL DEFAULT CURRENT_DATE, BTC000001 INT, BTC1 INT, BTC1000 INT);"

# Selects
# Address >= 0.00001 BTC
BTC000001=$(psql -d postgres -U postgres -t -c "select count(*) from (select address, sum(amount) / 100000000 as BTC from utxo group by address having sum(amount) / 100000000 >= 0.00001) B000001")

# Address >= 1 BTC
BTC1=$(psql -d postgres -U postgres -t -c "select count(*) from (select address, sum(amount) / 100000000 as BTC from utxo group by address having sum(amount) / 100000000 >= 1) B1")

# Whales Bitcoin, address >= 1000 BTC
BTC1000=$(psql -d postgres -U postgres -t -c "select count(*) from (select address, sum(amount) / 100000000 as BTC from utxo group by address having sum(amount) / 100000000 >= 1000) B1000")
psql -d postgres -U postgres -c "INSERT INTO address(BTC000001, BTC1, BTC1000) VALUES ($BTC000001, $BTC1, $BTC1000)"

psql -d postgres -U postgres -c "select * from address"

La versión en Inglés Exporting bitcoin utxos to a database.

Leave a Reply