Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tapdb: Federation DB fixes #583

Merged
merged 1 commit into from
Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions tapdb/sqlc/migrations/000009_universe_configs.down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE IF EXISTS federation_uni_sync_config;
35 changes: 35 additions & 0 deletions tapdb/sqlc/migrations/000009_universe_configs.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
DROP TABLE IF EXISTS federation_uni_sync_config;

-- This table contains universe (asset/asset group) specific federation sync
-- configuration.
CREATE TABLE IF NOT EXISTS federation_uni_sync_config (
-- namespace is the string representation of the universe identifier, and
-- ensures that there are no duplicate configs.
namespace VARCHAR NOT NULL PRIMARY KEY,

-- This field contains the byte serialized ID of the asset to which this
-- configuration is applicable.
asset_id BLOB CHECK(length(asset_id) = 32) NULL,

-- This field contains the byte serialized compressed group key public key
-- of the asset group to which this configuration is applicable.
group_key BLOB CHECK(LENGTH(group_key) = 33) NULL,

-- This field is an enum representing the proof type stored in the given
-- universe.
proof_type TEXT NOT NULL CHECK(proof_type IN ('issuance', 'transfer')),

-- This field is a boolean that indicates whether or not the given universe
-- should accept remote proof insertion via federation sync.
allow_sync_insert BOOLEAN NOT NULL,

-- This field is a boolean that indicates whether or not the given universe
-- should accept remote proof export via federation sync.
allow_sync_export BOOLEAN NOT NULL,

-- Both the asset ID and group key cannot be null at the same time.
CHECK (
(asset_id IS NOT NULL AND group_key IS NULL) OR
(asset_id IS NULL AND group_key IS NOT NULL)
)
);
1 change: 1 addition & 0 deletions tapdb/sqlc/models.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 8 additions & 6 deletions tapdb/sqlc/queries/universe.sql
Original file line number Diff line number Diff line change
Expand Up @@ -327,20 +327,22 @@ ON CONFLICT(proof_type)

-- name: QueryFederationGlobalSyncConfigs :many
SELECT proof_type, allow_sync_insert, allow_sync_export
FROM federation_global_sync_config;
FROM federation_global_sync_config
ORDER BY proof_type;

-- name: UpsertFederationUniSyncConfig :exec
INSERT INTO federation_uni_sync_config (
asset_id, group_key, proof_type, allow_sync_insert, allow_sync_export
namespace, asset_id, group_key, proof_type, allow_sync_insert, allow_sync_export
)
VALUES(
@asset_id, @group_key, @proof_type, @allow_sync_insert, @allow_sync_export
@namespace, @asset_id, @group_key, @proof_type, @allow_sync_insert, @allow_sync_export
)
ON CONFLICT(asset_id, group_key, proof_type)
ON CONFLICT(namespace)
DO UPDATE SET
allow_sync_insert = @allow_sync_insert,
allow_sync_export = @allow_sync_export;

-- name: QueryFederationUniSyncConfigs :many
SELECT asset_id, group_key, proof_type, allow_sync_insert, allow_sync_export
FROM federation_uni_sync_config;
SELECT namespace, asset_id, group_key, proof_type, allow_sync_insert, allow_sync_export
FROM federation_uni_sync_config
ORDER BY group_key NULLS LAST, asset_id NULLS LAST, proof_type;
17 changes: 11 additions & 6 deletions tapdb/sqlc/universe.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 9 additions & 12 deletions tapdb/universe_federation.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,10 +263,8 @@ func (u *UniverseFederationDB) UpsertFederationSyncConfig(
}

// Upsert universe specific sync configs.
for i := range uniSyncConfigs {
for _, config := range uniSyncConfigs {
var (
config = uniSyncConfigs[i]

uniID = config.UniverseID
groupPubKey []byte
assetIDBytes []byte
Expand All @@ -285,6 +283,7 @@ func (u *UniverseFederationDB) UpsertFederationSyncConfig(

err := db.UpsertFederationUniSyncConfig(
ctx, UpsertFedUniSyncConfigParams{
Namespace: uniID.String(),
AssetID: assetIDBytes,
GroupKey: groupPubKey,
ProofType: uniID.ProofType.String(),
Expand Down Expand Up @@ -379,20 +378,18 @@ func (u *UniverseFederationDB) QueryFederationSyncConfigs(
[]*universe.FedUniSyncConfig, len(uniDbConfigs),
)

for i := range uniDbConfigs {
conf := uniDbConfigs[i]

for i, config := range uniDbConfigs {
proofType, err := universe.ParseStrProofType(
conf.ProofType,
config.ProofType,
)
if err != nil {
return err
}

// Construct group key public key from bytes.
var pubKey *btcec.PublicKey
if conf.GroupKey != nil {
pubKey, err = btcec.ParsePubKey(conf.GroupKey)
if config.GroupKey != nil {
pubKey, err = btcec.ParsePubKey(config.GroupKey)
if err != nil {
return fmt.Errorf("unable to parse "+
"group key: %v", err)
Expand All @@ -401,7 +398,7 @@ func (u *UniverseFederationDB) QueryFederationSyncConfigs(

// Construct asset ID from bytes.
var assetID asset.ID
copy(assetID[:], conf.AssetID)
copy(assetID[:], config.AssetID)

uniID := universe.Identifier{
AssetID: assetID,
Expand All @@ -411,8 +408,8 @@ func (u *UniverseFederationDB) QueryFederationSyncConfigs(

uniConfigs[i] = &universe.FedUniSyncConfig{
UniverseID: uniID,
AllowSyncInsert: conf.AllowSyncInsert,
AllowSyncExport: conf.AllowSyncExport,
AllowSyncInsert: config.AllowSyncInsert,
AllowSyncExport: config.AllowSyncExport,
}
}
return nil
Expand Down
75 changes: 71 additions & 4 deletions tapdb/universe_federation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"time"

"github.com/lightninglabs/taproot-assets/fn"
"github.com/lightninglabs/taproot-assets/internal/test"
"github.com/lightninglabs/taproot-assets/tapdb/sqlc"
"github.com/lightninglabs/taproot-assets/universe"
"github.com/lightningnetwork/lnd/clock"
Expand Down Expand Up @@ -114,9 +115,9 @@ func TestFederationConfigDefault(t *testing.T) {
require.Equal(t, defaultGlobalSyncConfigs, globalConfig)
}

// TestFederationGlobalConfigCRUD tests that we're able to properly update the
// global and local federation configs.
func TestFederationGlobalConfigCRUD(t *testing.T) {
// TestFederationConfigCRUD tests that we're able to properly update the global
// and local federation configs.
func TestFederationConfigCRUD(t *testing.T) {
t.Parallel()

testClock := clock.NewTestClock(time.Now())
Expand Down Expand Up @@ -166,7 +167,7 @@ func TestFederationGlobalConfigCRUD(t *testing.T) {
expectedCfgs = append(newGlobalProof, newGlobalTransfer...)
require.Equal(t, expectedCfgs, dbGlobalCfg)

// Finally, we should be able to update them both in the same txn.
// We should be able to update them both in the same txn.
for _, cfg := range expectedCfgs {
cfg.AllowSyncInsert = false
cfg.AllowSyncExport = false
Expand All @@ -178,4 +179,70 @@ func TestFederationGlobalConfigCRUD(t *testing.T) {
dbGlobalCfg, _, err = fedDB.QueryFederationSyncConfigs(ctx)
require.NoError(t, err)
require.Equal(t, expectedCfgs, dbGlobalCfg)

// Finally, if we insert the current config again, we should see no
// change in the returned configs.
singleCfg := fn.MakeSlice(dbGlobalCfg[0])
err = fedDB.UpsertFederationSyncConfig(ctx, singleCfg, nil)
require.NoError(t, err)

dbGlobalCfg, _, err = fedDB.QueryFederationSyncConfigs(ctx)
require.NoError(t, err)
require.Equal(t, expectedCfgs, dbGlobalCfg)

// Now, create configs for specific assets.
randAssetIDBytes := test.RandBytes(32)
randGroupKey := test.RandPubKey(t)
groupCfg := &universe.FedUniSyncConfig{
UniverseID: universe.Identifier{
GroupKey: randGroupKey,
ProofType: universe.ProofTypeIssuance,
},
AllowSyncInsert: true,
AllowSyncExport: false,
}
assetCfg := &universe.FedUniSyncConfig{
UniverseID: universe.Identifier{
ProofType: universe.ProofTypeTransfer,
},
AllowSyncInsert: false,
AllowSyncExport: true,
}
copy(assetCfg.UniverseID.AssetID[:], randAssetIDBytes)

// Before insertion, there should be no asset-specific configs.
_, dbLocalCfg, err := fedDB.QueryFederationSyncConfigs(ctx)
require.NoError(t, err)
require.Empty(t, dbLocalCfg)

// Next, store the asset configs and verify that we get the same configs
// back from a query.
localCfg := fn.MakeSlice(groupCfg, assetCfg)
err = fedDB.UpsertFederationSyncConfig(ctx, nil, localCfg)
require.NoError(t, err)

_, dbLocalCfg, err = fedDB.QueryFederationSyncConfigs(ctx)
require.NoError(t, err)
require.Equal(t, localCfg, dbLocalCfg)

// We should be able to overwrite a stored config.
groupNewCfg := &universe.FedUniSyncConfig{
UniverseID: universe.Identifier{
GroupKey: randGroupKey,
ProofType: universe.ProofTypeIssuance,
},
AllowSyncInsert: true,
AllowSyncExport: true,
}
err = fedDB.UpsertFederationSyncConfig(
ctx, nil, fn.MakeSlice(groupNewCfg),
)
require.NoError(t, err)

_, dbLocalCfg, err = fedDB.QueryFederationSyncConfigs(ctx)
require.NoError(t, err)
require.NotEqual(t, localCfg, dbLocalCfg)

localCfg = fn.MakeSlice(groupNewCfg, assetCfg)
require.Equal(t, localCfg, dbLocalCfg)
}