Как я пытаюсь внедрить SQL Bitcoin базы данных для моего библиотека Perl, я искал способ эффективно хранить структуру дерева блоков. Так я узнал об идее, которая вроде опрятно: вложенности множеств.
Вот один документ, который объясняет его (это не один я на самом деле используется в качестве одного я использовал не на английском, так что я должен был найти другой для вас): https://communities.bmc.com/communities/docs / DOC-9902
EDIT: википедия страница кажется, тоже хорошо.
Я думаю, что это довольно метод тесак, но немного трудно понять.
Вот MySQL код, который я написал до сих пор (я не ставил здесь какие-то взгляды, но я поставил основные таблицы, даже если они не относятся к предмету данной теме):
Код:
-- Таблица "блоки" на самом деле содержит только блок заголовков
CREATE TABLE блоки (
хэш-символ (32) двоичный первичный ключ,
версия целое число по умолчанию 1,
hashPrev символ (32) двоичный не нулевой,
hashMerkleRoot символ (32), не двоичная нуль,
NTime целое число без знака не равно нулю,
Nbits целое число без знака не равно нулю,
nNonce целое число без знака не равно нулю,
ключ (hashMerkleRoot),
ключ (hashPrev)
);
-- Мы вставить блок генезиса здесь некоторые триггера не будут вести себя хорошо
-- с таблицей пустых "блоками.
INSERT INTO значений блоков (
unhex ("6FE28C0AB6F1B372C1A6A246AE63F74F931E8365E15A089C68D6190000000000"),
1,
unhex ("0000000000000000000000000000000000000000000000000000000000000000"),
unhex ("3BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4A"),
1231006505,
486604799,
2083236893
);
-- Вид бесхозных блоков
-- (Обратите внимание, что мы не используем любые "Посмотреть" Приставка в названии здесь)
CREATE VIEW orphan_blocks AS
Выберите.*
ОТ блокирует LEFT JOIN блоки б
ON a.hashPrev = b.hash
ГДЕ b.hash IS NULL;
-- Меркл транзакционных дерева хранятся в их собственной таблице
CREATE TABLE Merkle_trees (
Корневой символ (32) двоичная не нулевые,
IDX целое число без знака не равно нулю,
гашиш символ (32) двоичные,
Первичный ключ (корень, IDX),
ключ (корень)
);
-- операции
CREATE TABLE операций (
хэш-символ (32) двоичный первичный ключ,
версия целое число,
Locktime целое число без знака,
);
-- входы транзакций
CREATE TABLE tx_in (
хэш-символ (32) двоичной,
prevout_hash символ (32) двоичной,
prevout_n целое число без знака,
scriptSig блоб,
Последовательность целое число без знака,
Первичный ключ (хэш, prevout_hash, prevout_n),
Ключ (хэш)
)
-- выходы транзакций
CREATE TABLE tx_out (
tx_out_id целое число без знака первичного ключа auto_increment,
хэш-символ (32) двоичной,
целое значение,
scriptPubKey блоб,
Ключ (хэш)
);
-- Функция для вычисления цели из Nbits
CREATE целевой функции (биты с плавающей точкой)
ВОЗВРАТ РЕАЛ DETERMINISTIC
ВОЗВРАТ моды (биты, 0x1000000) * пау (256, биты Дива 0x1000000 - 3);
-- Для того, чтобы создать структуру блока дерева,
-- мы будем использовать модель интервала.
-- Каждый узел (т.е. каждый блок) будет иметь левый
-- и правый край. Мы должны обеспечить, чтобы по убыванию
-- блоки имеют края внутри краев своего родителя.
CREATE TABLE block_tree (
узел символ (32) двоичный первичный ключ,
L целое число без знака не равно нулю,
р целое число без знака не нулевой чек (R > Л),
высота целое число без знака не нуль
);
-- Вставляем узел генезис вручную.
-- Левый край 0, правый край 1, высота 0.
INSERT INTO значений block_tree (
unhex ("6FE28C0AB6F1B372C1A6A246AE63F74F931E8365E15A089C68D6190000000000"),
0,
1,
0
);
CREATE TRIGGER add_block_in_tree ПОСЛЕ INSERT ON блоков
ДЛЯ КАЖДОЙ ROW
НАЧАТЬ
ОБНОВЛЕНИЕ block_tree т, block_tree г
SET t.L = t.L + 2
ГДЕ r.node = new.hashPrev
И t.L >= R.D;
ОБНОВЛЕНИЕ block_tree т, block_tree г
SET t.D = t.D + 2
ГДЕ r.node = new.hashPrev
И t.D >= R.D;
INSERT INTO block_tree (узел, L, R, высота)
ВЫБОР new.hash, r.D, r.D + 1, + 1 r.height
ОТ block_tree г
Где r.node = new.hashPrev;
КОНЕЦ;
CREATE TABLE блоки (
хэш-символ (32) двоичный первичный ключ,
версия целое число по умолчанию 1,
hashPrev символ (32) двоичный не нулевой,
hashMerkleRoot символ (32), не двоичная нуль,
NTime целое число без знака не равно нулю,
Nbits целое число без знака не равно нулю,
nNonce целое число без знака не равно нулю,
ключ (hashMerkleRoot),
ключ (hashPrev)
);
-- Мы вставить блок генезиса здесь некоторые триггера не будут вести себя хорошо
-- с таблицей пустых "блоками.
INSERT INTO значений блоков (
unhex ("6FE28C0AB6F1B372C1A6A246AE63F74F931E8365E15A089C68D6190000000000"),
1,
unhex ("0000000000000000000000000000000000000000000000000000000000000000"),
unhex ("3BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4A"),
1231006505,
486604799,
2083236893
);
-- Вид бесхозных блоков
-- (Обратите внимание, что мы не используем любые "Посмотреть" Приставка в названии здесь)
CREATE VIEW orphan_blocks AS
Выберите.*
ОТ блокирует LEFT JOIN блоки б
ON a.hashPrev = b.hash
ГДЕ b.hash IS NULL;
-- Меркл транзакционных дерева хранятся в их собственной таблице
CREATE TABLE Merkle_trees (
Корневой символ (32) двоичная не нулевые,
IDX целое число без знака не равно нулю,
гашиш символ (32) двоичные,
Первичный ключ (корень, IDX),
ключ (корень)
);
-- операции
CREATE TABLE операций (
хэш-символ (32) двоичный первичный ключ,
версия целое число,
Locktime целое число без знака,
);
-- входы транзакций
CREATE TABLE tx_in (
хэш-символ (32) двоичной,
prevout_hash символ (32) двоичной,
prevout_n целое число без знака,
scriptSig блоб,
Последовательность целое число без знака,
Первичный ключ (хэш, prevout_hash, prevout_n),
Ключ (хэш)
)
-- выходы транзакций
CREATE TABLE tx_out (
tx_out_id целое число без знака первичного ключа auto_increment,
хэш-символ (32) двоичной,
целое значение,
scriptPubKey блоб,
Ключ (хэш)
);
-- Функция для вычисления цели из Nbits
CREATE целевой функции (биты с плавающей точкой)
ВОЗВРАТ РЕАЛ DETERMINISTIC
ВОЗВРАТ моды (биты, 0x1000000) * пау (256, биты Дива 0x1000000 - 3);
-- Для того, чтобы создать структуру блока дерева,
-- мы будем использовать модель интервала.
-- Каждый узел (т.е. каждый блок) будет иметь левый
-- и правый край. Мы должны обеспечить, чтобы по убыванию
-- блоки имеют края внутри краев своего родителя.
CREATE TABLE block_tree (
узел символ (32) двоичный первичный ключ,
L целое число без знака не равно нулю,
р целое число без знака не нулевой чек (R > Л),
высота целое число без знака не нуль
);
-- Вставляем узел генезис вручную.
-- Левый край 0, правый край 1, высота 0.
INSERT INTO значений block_tree (
unhex ("6FE28C0AB6F1B372C1A6A246AE63F74F931E8365E15A089C68D6190000000000"),
0,
1,
0
);
CREATE TRIGGER add_block_in_tree ПОСЛЕ INSERT ON блоков
ДЛЯ КАЖДОЙ ROW
НАЧАТЬ
ОБНОВЛЕНИЕ block_tree т, block_tree г
SET t.L = t.L + 2
ГДЕ r.node = new.hashPrev
И t.L >= R.D;
ОБНОВЛЕНИЕ block_tree т, block_tree г
SET t.D = t.D + 2
ГДЕ r.node = new.hashPrev
И t.D >= R.D;
INSERT INTO block_tree (узел, L, R, высота)
ВЫБОР new.hash, r.D, r.D + 1, + 1 r.height
ОТ block_tree г
Где r.node = new.hashPrev;
КОНЕЦ;
Курок "add_block_in_tree" должен работать, когда блок, родитель которого, как известно вставляется. Но это не будет работать, если блок вставляется перед его родителем. Должна быть обеспечена возможность закодировать это, но это немного сложнее.
Во всяком случае, если кто-то также заинтересованы в этой модели, я бы с удовольствием услышать предложения.