Skip to content

Commit 1afc90b

Browse files
committed
tapdb: add new multiverse root overlay tables and queries
This commit adds two new tables for the two multiverse trees we currently have: multiverse_roots (will currently only contain two entries, one for the issuance and one for the transfer multiverse roots) and multiverse_leaves (which will contain an entry for each issuance and proof universe we currently have). We already have all information needed to fill these tables for existing universes, so we can use conditional INSERT statements to create the entries for all existing universes. Any new universes will be added through the new upsert methods added.
1 parent 7400499 commit 1afc90b

File tree

7 files changed

+269
-1
lines changed

7 files changed

+269
-1
lines changed

tapdb/postgres.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ var (
3939
"INTEGER PRIMARY KEY": "SERIAL PRIMARY KEY",
4040
"BIGINT PRIMARY KEY": "BIGSERIAL PRIMARY KEY",
4141
"TIMESTAMP": "TIMESTAMP WITHOUT TIME ZONE",
42+
"UNHEX": "DECODE",
4243
}
4344
)
4445

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
DROP INDEX IF EXISTS multiverse_leaves_unique;
2+
DROP TABLE IF EXISTS multiverse_leaves;
3+
DROP TABLE IF EXISTS multiverse_roots;
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
CREATE TABLE IF NOT EXISTS multiverse_roots (
2+
id BIGINT PRIMARY KEY,
3+
4+
-- For the namespace root, we set the foreign key constraint evaluation to
5+
-- be deferred until after the database transaction ends. Otherwise, if the
6+
-- root of the SMT is deleted temporarily before inserting a new root, then
7+
-- this constraint is violated as there's no longer a root that this
8+
-- universe tree can point to.
9+
namespace_root VARCHAR UNIQUE NOT NULL REFERENCES mssmt_roots(namespace) DEFERRABLE INITIALLY DEFERRED,
10+
11+
-- This field is an enum representing the proof type stored in the given
12+
-- universe.
13+
proof_type TEXT NOT NULL CHECK(proof_type IN ('issuance', 'transfer'))
14+
);
15+
16+
CREATE TABLE IF NOT EXISTS multiverse_leaves (
17+
id BIGINT PRIMARY KEY,
18+
19+
multiverse_root_id BIGINT NOT NULL REFERENCES multiverse_roots(id),
20+
21+
asset_id BLOB CHECK(length(asset_id) = 32),
22+
23+
-- We use the 32 byte schnorr key here as this is what's used to derive the
24+
-- top-level Taproot Asset commitment key.
25+
group_key BLOB CHECK(LENGTH(group_key) = 32),
26+
27+
leaf_node_key BLOB NOT NULL,
28+
29+
leaf_node_namespace VARCHAR NOT NULL,
30+
31+
-- Both the asset ID and group key cannot be null at the same time.
32+
CHECK (
33+
(asset_id IS NOT NULL AND group_key IS NULL) OR
34+
(asset_id IS NULL AND group_key IS NOT NULL)
35+
)
36+
);
37+
38+
CREATE UNIQUE INDEX multiverse_leaves_unique ON multiverse_leaves (
39+
leaf_node_key, leaf_node_namespace
40+
);
41+
42+
-- If there already is a multiverse root entry in the mssmt_roots for the
43+
-- issuance or transfer multiverses, add them to the multiverse_roots table as
44+
-- well. Both statements are no-ops if the root doesn't exist yet.
45+
INSERT INTO multiverse_roots (namespace_root, proof_type)
46+
SELECT 'multiverse-issuance', 'issuance'
47+
WHERE EXISTS (
48+
SELECT 1 FROM mssmt_roots WHERE namespace = 'multiverse-issuance'
49+
);
50+
51+
INSERT INTO multiverse_roots (namespace_root, proof_type)
52+
SELECT 'multiverse-transfer', 'transfer'
53+
WHERE EXISTS (
54+
SELECT 1 FROM mssmt_roots WHERE namespace = 'multiverse-transfer'
55+
);
56+
57+
-- And now we create the multiverse_leaves entries for the multiverse roots.
58+
-- This is a no-op if the multiverse root doesn't exist yet.
59+
INSERT INTO multiverse_leaves (
60+
multiverse_root_id, asset_id, group_key, leaf_node_key, leaf_node_namespace
61+
) SELECT
62+
(SELECT id from multiverse_roots mr where mr.namespace_root = 'multiverse-issuance'),
63+
CASE WHEN ur.group_key IS NULL THEN ur.asset_id ELSE NULL END,
64+
ur.group_key,
65+
-- UNHEX() only exists in SQLite and it doesn't take a second argument
66+
-- (the 'hex' part). But it also doesn't complain about it, so we can
67+
-- leave it in for the Postgres version which is replaced in-memory to
68+
-- DECODE() which needs the 'hex' argument.
69+
UNHEX(REPLACE(ur.namespace_root, 'issuance-', ''), 'hex'),
70+
ur.namespace_root
71+
FROM universe_roots ur
72+
WHERE ur.namespace_root LIKE 'issuance-%';
73+
74+
INSERT INTO multiverse_leaves (
75+
multiverse_root_id, asset_id, group_key, leaf_node_key, leaf_node_namespace
76+
) SELECT
77+
(SELECT id from multiverse_roots mr where mr.namespace_root = 'multiverse-transfer'),
78+
CASE WHEN ur.group_key IS NULL THEN ur.asset_id ELSE NULL END,
79+
ur.group_key,
80+
-- UNHEX() only exists in SQLite and it doesn't take a second argument
81+
-- (the 'hex' part). But it also doesn't complain about it, so we can
82+
-- leave it in for the Postgres version which is replaced in-memory to
83+
-- DECODE() which needs the 'hex' argument.
84+
UNHEX(REPLACE(ur.namespace_root, 'transfer-', ''), 'hex'),
85+
ur.namespace_root
86+
FROM universe_roots ur
87+
WHERE ur.namespace_root LIKE 'transfer-%';

tapdb/sqlc/models.go

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tapdb/sqlc/querier.go

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tapdb/sqlc/queries/universe.sql

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,4 +480,38 @@ WHERE
480480
(timestamp >= sqlc.narg('min_timestamp')
481481
OR sqlc.narg('min_timestamp') IS NULL) AND
482482
(attempt_counter >= sqlc.narg('min_attempt_counter')
483-
OR sqlc.narg('min_attempt_counter') IS NULL);
483+
OR sqlc.narg('min_attempt_counter') IS NULL);
484+
485+
-- name: UpsertMultiverseRoot :one
486+
INSERT INTO multiverse_roots (namespace_root, proof_type)
487+
VALUES (@namespace_root, @proof_type)
488+
ON CONFLICT (namespace_root)
489+
-- This is a no-op to allow returning the ID.
490+
DO UPDATE SET namespace_root = EXCLUDED.namespace_root
491+
RETURNING id;
492+
493+
-- name: UpsertMultiverseLeaf :one
494+
INSERT INTO multiverse_leaves (
495+
multiverse_root_id, asset_id, group_key, leaf_node_key, leaf_node_namespace
496+
) VALUES (
497+
@multiverse_root_id, @asset_id, @group_key, @leaf_node_key,
498+
@leaf_node_namespace
499+
)
500+
ON CONFLICT (leaf_node_key, leaf_node_namespace)
501+
-- This is a no-op to allow returning the ID.
502+
DO UPDATE SET leaf_node_key = EXCLUDED.leaf_node_key,
503+
leaf_node_namespace = EXCLUDED.leaf_node_namespace
504+
RETURNING id;
505+
506+
-- name: DeleteMultiverseLeaf :exec
507+
DELETE FROM multiverse_leaves
508+
WHERE leaf_node_namespace = @namespace AND leaf_node_key = @leaf_node_key;
509+
510+
-- name: QueryMultiverseLeaves :many
511+
SELECT r.namespace_root, r.proof_type, l.asset_id, l.group_key, l.leaf_node_key
512+
FROM multiverse_leaves l
513+
JOIN multiverse_roots r
514+
ON l.multiverse_root_id = r.id
515+
WHERE r.proof_type = @proof_type AND
516+
(l.asset_id = @asset_id OR @asset_id IS NULL) AND
517+
(l.group_key = @group_key OR @group_key IS NULL);

tapdb/sqlc/universe.sql.go

Lines changed: 124 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)