From de8a12079ddd4fbece28e3645ad6a92164e1b3e8 Mon Sep 17 00:00:00 2001 From: Angelo De Caro Date: Fri, 5 Jul 2024 14:44:01 +0200 Subject: [PATCH] fixup! db extensions Signed-off-by: Angelo De Caro --- token/sdk/dig/providers.go | 8 ++- token/sdk/dig/sdk.go | 2 + token/services/db/sql/driver/unity/driver.go | 27 +++++++--- token/services/db/sql/ext/driver.go | 6 ++- token/services/db/sql/identity.go | 4 +- token/services/db/sql/tokenlock.go | 4 +- token/services/db/sql/tokens.go | 19 +++---- token/services/db/sql/transactions.go | 4 +- token/services/db/sql/wallet.go | 4 +- .../interop/htlc/db/sql/tokendbext.go | 51 +++++++++++++++++-- .../selector/sherdlock/manager_test.go | 5 +- token/services/tokendb/db/memory/memory.go | 10 ++-- token/services/tokendb/db/sql/driver.go | 8 ++- 13 files changed, 115 insertions(+), 37 deletions(-) diff --git a/token/sdk/dig/providers.go b/token/sdk/dig/providers.go index 6ac8344ff..24ec34224 100644 --- a/token/sdk/dig/providers.go +++ b/token/sdk/dig/providers.go @@ -15,6 +15,7 @@ import ( "github.com/hyperledger-labs/fabric-token-sdk/token/services/db" dbdriver "github.com/hyperledger-labs/fabric-token-sdk/token/services/db/driver" "github.com/hyperledger-labs/fabric-token-sdk/token/services/db/sql/driver/unity" + "github.com/hyperledger-labs/fabric-token-sdk/token/services/db/sql/ext" "github.com/hyperledger-labs/fabric-token-sdk/token/services/identitydb" "github.com/hyperledger-labs/fabric-token-sdk/token/services/network" "github.com/hyperledger-labs/fabric-token-sdk/token/services/network/driver" @@ -86,8 +87,11 @@ type DBDriverResult struct { IdentityDBDriver db.NamedDriver[dbdriver.IdentityDBDriver] `group:"identitydb-drivers"` } -func NewDBDrivers() DBDriverResult { - ttxDBDriver, tokenDBDriver, tokenLockDBDriver, auditDBDriver, identityDBDriver := unity.NewDBDrivers() +func NewDBDrivers(in struct { + dig.In + TokenDBExtensions []ext.Factory[ext.TokenDBExtension] `group:"tokendb-extensions"` +}) DBDriverResult { + ttxDBDriver, tokenDBDriver, tokenLockDBDriver, auditDBDriver, identityDBDriver := unity.NewDBDrivers(in.TokenDBExtensions) return DBDriverResult{ TTXDBDriver: ttxDBDriver, TokenDBDriver: tokenDBDriver, diff --git a/token/sdk/dig/sdk.go b/token/sdk/dig/sdk.go index 744bdd0ad..5dba60c49 100644 --- a/token/sdk/dig/sdk.go +++ b/token/sdk/dig/sdk.go @@ -41,6 +41,7 @@ import ( kvs2 "github.com/hyperledger-labs/fabric-token-sdk/token/services/identity/kvs" "github.com/hyperledger-labs/fabric-token-sdk/token/services/identitydb" "github.com/hyperledger-labs/fabric-token-sdk/token/services/interop/htlc" + "github.com/hyperledger-labs/fabric-token-sdk/token/services/interop/htlc/db/sql" logging2 "github.com/hyperledger-labs/fabric-token-sdk/token/services/logging" "github.com/hyperledger-labs/fabric-token-sdk/token/services/network" _ "github.com/hyperledger-labs/fabric-token-sdk/token/services/network/fabric" @@ -118,6 +119,7 @@ func (p *SDK) Install() error { p.Container().Provide(digutils.Identity[*auditdb.Manager](), dig.As(new(auditor.AuditDBProvider))), p.Container().Provide(NewIdentityDBManager), p.Container().Provide(NewTokenLockDBManager), + p.Container().Provide(sql.NewHTLCTokenDBExtensionFactory, dig.Group("tokendb-extensions")), p.Container().Provide(digutils.Identity[*kvs.KVS](), dig.As(new(kvs2.KVS))), p.Container().Provide(identity.NewDBStorageProvider), p.Container().Provide(auditor.NewManager), diff --git a/token/services/db/sql/driver/unity/driver.go b/token/services/db/sql/driver/unity/driver.go index 40be06e12..b8aa2e005 100644 --- a/token/services/db/sql/driver/unity/driver.go +++ b/token/services/db/sql/driver/unity/driver.go @@ -7,11 +7,14 @@ SPDX-License-Identifier: Apache-2.0 package unity import ( + "database/sql" + "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils" "github.com/hyperledger-labs/fabric-token-sdk/token" "github.com/hyperledger-labs/fabric-token-sdk/token/services/db" dbdriver "github.com/hyperledger-labs/fabric-token-sdk/token/services/db/driver" sqldb "github.com/hyperledger-labs/fabric-token-sdk/token/services/db/sql" + "github.com/hyperledger-labs/fabric-token-sdk/token/services/db/sql/ext" "github.com/pkg/errors" ) @@ -22,12 +25,14 @@ const ( ) type Driver struct { - DBOpener *sqldb.DBOpener + DBOpener *sqldb.DBOpener + TokenDBExtensions []ext.Factory[ext.TokenDBExtension] `optional=true` } -func NewDriver() *Driver { +func NewDriver(tokenDBExtensions []ext.Factory[ext.TokenDBExtension]) *Driver { return &Driver{ - DBOpener: sqldb.NewSQLDBOpener(optsKey, envVarKey), + DBOpener: sqldb.NewSQLDBOpener(optsKey, envVarKey), + TokenDBExtensions: tokenDBExtensions, } } @@ -36,7 +41,17 @@ func (d *Driver) OpenTokenTransactionDB(cp dbdriver.ConfigProvider, tmsID token. } func (d *Driver) OpenTokenDB(cp dbdriver.ConfigProvider, tmsID token.TMSID) (dbdriver.TokenDB, error) { - return openDB(d.DBOpener, cp, tmsID, sqldb.NewTokenDB) + return openDB(d.DBOpener, cp, tmsID, func(db *sql.DB, tablePrefix string, createSchema bool) (dbdriver.TokenDB, error) { + extensions := make([]ext.TokenDBExtension, len(d.TokenDBExtensions)) + for i, factory := range d.TokenDBExtensions { + ext, err := factory.NewExtension(tablePrefix) + if err != nil { + return nil, errors.WithMessagef(err, "failed creating token DB extension [%d]", i) + } + extensions = append(extensions, ext) + } + return sqldb.NewTokenDB(db, tablePrefix, createSchema, extensions...) + }) } func (d *Driver) OpenTokenLockDB(cp dbdriver.ConfigProvider, tmsID token.TMSID) (dbdriver.TokenLockDB, error) { @@ -107,8 +122,8 @@ func (t *IdentityDBDriver) OpenIdentityDB(cp dbdriver.ConfigProvider, tmsID toke return t.Driver.OpenIdentityDB(cp, tmsID) } -func NewDBDrivers() (db.NamedDriver[dbdriver.TTXDBDriver], db.NamedDriver[dbdriver.TokenDBDriver], db.NamedDriver[dbdriver.TokenLockDBDriver], db.NamedDriver[dbdriver.AuditDBDriver], db.NamedDriver[dbdriver.IdentityDBDriver]) { - root := NewDriver() +func NewDBDrivers(tokenDBExtensions []ext.Factory[ext.TokenDBExtension]) (db.NamedDriver[dbdriver.TTXDBDriver], db.NamedDriver[dbdriver.TokenDBDriver], db.NamedDriver[dbdriver.TokenLockDBDriver], db.NamedDriver[dbdriver.AuditDBDriver], db.NamedDriver[dbdriver.IdentityDBDriver]) { + root := NewDriver(tokenDBExtensions) return db.NamedDriver[dbdriver.TTXDBDriver]{Name: "unity", Driver: &TtxDBDriver{Driver: root}}, db.NamedDriver[dbdriver.TokenDBDriver]{Name: "unity", Driver: &TokenDBDriver{Driver: root}}, db.NamedDriver[dbdriver.TokenLockDBDriver]{Name: "unity", Driver: &TokenLockDBDriver{Driver: root}}, diff --git a/token/services/db/sql/ext/driver.go b/token/services/db/sql/ext/driver.go index b62363559..a17cdbeea 100644 --- a/token/services/db/sql/ext/driver.go +++ b/token/services/db/sql/ext/driver.go @@ -14,7 +14,7 @@ import ( ) type Extension interface { - GetSchema() string + GetSchema(tablePrefix string) string } type TokenDBExtension interface { @@ -23,3 +23,7 @@ type TokenDBExtension interface { StoreToken(tx *sql.Tx, tr driver.TokenRecord, owners []string) error DeleteTokens(tx *sql.Tx, deletedBy string, ids ...*token.ID) error } + +type Factory[T Extension] interface { + NewExtension(prefix string) (T, error) +} diff --git a/token/services/db/sql/identity.go b/token/services/db/sql/identity.go index c244d37a0..91998093d 100644 --- a/token/services/db/sql/identity.go +++ b/token/services/db/sql/identity.go @@ -64,7 +64,7 @@ func NewIdentityDB(db *sql.DB, tablePrefix string, createSchema bool, signerInfo Signers: tables.Signers, }, signerInfoCache) if createSchema { - if err = initSchema(db, identityDB.GetSchema()); err != nil { + if err = initSchema(db, identityDB.GetSchema(tablePrefix)); err != nil { return nil, err } } @@ -267,7 +267,7 @@ func (w *IdentityConfigurationIterator) Next() (driver.IdentityConfiguration, er return c, err } -func (db *IdentityDB) GetSchema() string { +func (db *IdentityDB) GetSchema(string) string { return fmt.Sprintf(` -- IdentityConfigurations CREATE TABLE IF NOT EXISTS %s ( diff --git a/token/services/db/sql/tokenlock.go b/token/services/db/sql/tokenlock.go index 8bf3c912e..8fce4da8b 100644 --- a/token/services/db/sql/tokenlock.go +++ b/token/services/db/sql/tokenlock.go @@ -41,7 +41,7 @@ func NewTokenLockDB(db *sql.DB, tablePrefix string, createSchema bool) (driver.T identityDB := newTokenLockDB(db, tokenLockTables{TokenLocks: tables.TokenLocks}) if createSchema { - if err = initSchema(db, identityDB.GetSchema()); err != nil { + if err = initSchema(db, identityDB.GetSchema(tablePrefix)); err != nil { return nil, err } } @@ -64,7 +64,7 @@ func (db *TokenLockDB) UnlockByTxID(consumerTxID transaction.ID) error { return err } -func (db *TokenLockDB) GetSchema() string { +func (db *TokenLockDB) GetSchema(string) string { return fmt.Sprintf(` -- TokenLocks CREATE TABLE IF NOT EXISTS %s ( diff --git a/token/services/db/sql/tokens.go b/token/services/db/sql/tokens.go index 2d7df083a..fef2715c4 100644 --- a/token/services/db/sql/tokens.go +++ b/token/services/db/sql/tokens.go @@ -34,14 +34,15 @@ type TokenDB struct { extensions []ext.TokenDBExtension } -func newTokenDB(db *sql.DB, tables tokenTables) *TokenDB { +func newTokenDB(db *sql.DB, tables tokenTables, extensions ...ext.TokenDBExtension) *TokenDB { return &TokenDB{ - db: db, - table: tables, + db: db, + table: tables, + extensions: extensions, } } -func NewTokenDB(db *sql.DB, tablePrefix string, createSchema bool) (driver.TokenDB, error) { +func NewTokenDB(db *sql.DB, tablePrefix string, createSchema bool, extensions ...ext.TokenDBExtension) (driver.TokenDB, error) { tables, err := getTableNames(tablePrefix) if err != nil { return nil, errors.Wrapf(err, "failed to get table names") @@ -52,13 +53,13 @@ func NewTokenDB(db *sql.DB, tablePrefix string, createSchema bool) (driver.Token Ownership: tables.Ownership, PublicParams: tables.PublicParams, Certifications: tables.Certifications, - }) + }, extensions...) if createSchema { - if err = initSchema(db, tokenDB.GetSchema()); err != nil { + if err = initSchema(db, tokenDB.GetSchema(tablePrefix)); err != nil { return nil, err } for _, extension := range tokenDB.extensions { - if err = initSchema(db, extension.GetSchema()); err != nil { + if err = initSchema(db, extension.GetSchema(tablePrefix)); err != nil { return nil, err } } @@ -82,7 +83,7 @@ func (db *TokenDB) StoreToken(tr driver.TokenRecord, owners []string) (err error if err1 := tx.Rollback(); err1 != nil { logger.Errorf("error rolling back: %s", err1.Error()) } - return + return err } } if err = tx.Commit(); err != nil { @@ -754,7 +755,7 @@ func (db *TokenDB) GetCertifications(ids []*token.ID) ([][]byte, error) { return certifications, nil } -func (db *TokenDB) GetSchema() string { +func (db *TokenDB) GetSchema(string) string { return fmt.Sprintf(` -- Tokens CREATE TABLE IF NOT EXISTS %s ( diff --git a/token/services/db/sql/transactions.go b/token/services/db/sql/transactions.go index 7e40e2a13..665dbc9bf 100644 --- a/token/services/db/sql/transactions.go +++ b/token/services/db/sql/transactions.go @@ -57,7 +57,7 @@ func NewTransactionDB(db *sql.DB, tablePrefix string, createSchema bool) (driver TransactionEndorseAck: tables.TransactionEndorseAck, }) if createSchema { - if err = initSchema(db, transactionsDB.GetSchema()); err != nil { + if err = initSchema(db, transactionsDB.GetSchema(tablePrefix)); err != nil { return nil, err } } @@ -253,7 +253,7 @@ func (db *TransactionDB) SetStatus(txID string, status driver.TxStatus, message return } -func (db *TransactionDB) GetSchema() string { +func (db *TransactionDB) GetSchema(string) string { return fmt.Sprintf(` -- requests CREATE TABLE IF NOT EXISTS %s ( diff --git a/token/services/db/sql/wallet.go b/token/services/db/sql/wallet.go index 543d41dce..168496bd7 100644 --- a/token/services/db/sql/wallet.go +++ b/token/services/db/sql/wallet.go @@ -40,7 +40,7 @@ func NewWalletDB(db *sql.DB, tablePrefix string, createSchema bool) (driver.Wall walletDB := newWalletDB(db, walletTables{Wallets: tables.Wallets}) if createSchema { - if err = initSchema(db, walletDB.GetSchema()); err != nil { + if err = initSchema(db, walletDB.GetSchema(tablePrefix)); err != nil { return nil, errors.Wrapf(err, "failed to create schema") } } @@ -127,7 +127,7 @@ func (db *WalletDB) IdentityExists(identity token.Identity, wID driver.WalletID, return result != "" } -func (db *WalletDB) GetSchema() string { +func (db *WalletDB) GetSchema(string) string { return fmt.Sprintf(` -- Wallets CREATE TABLE IF NOT EXISTS %s ( diff --git a/token/services/interop/htlc/db/sql/tokendbext.go b/token/services/interop/htlc/db/sql/tokendbext.go index f2868dd62..01225f8a4 100644 --- a/token/services/interop/htlc/db/sql/tokendbext.go +++ b/token/services/interop/htlc/db/sql/tokendbext.go @@ -10,29 +10,48 @@ import ( "database/sql" "encoding/json" "fmt" + "regexp" "runtime/debug" + "strings" + + "github.com/hyperledger-labs/fabric-token-sdk/token/services/db/sql/ext" "github.com/hyperledger-labs/fabric-token-sdk/token/services/db/driver" "github.com/hyperledger-labs/fabric-token-sdk/token/services/interop/htlc" "github.com/hyperledger-labs/fabric-token-sdk/token/services/logging" + "github.com/hyperledger-labs/fabric-token-sdk/token/token" "github.com/pkg/errors" ) var logger = logging.MustGetLogger("token-sdk.sql.htlc") -type htlcTokenDBExtensionTables struct { +type tableNames struct { Tokens string } +type HTLCTokenDBExtensionFactory struct{} + +func NewHTLCTokenDBExtensionFactory() *HTLCTokenDBExtensionFactory { + return &HTLCTokenDBExtensionFactory{} +} + +func (H *HTLCTokenDBExtensionFactory) NewExtension(prefix string) (ext.TokenDBExtension, error) { + return NewHTLCTokenDBExtension(prefix) +} + type HTLCTokenDBExtension struct { - table htlcTokenDBExtensionTables + table tableNames } -func NewHTLCTokenDBExtension(table htlcTokenDBExtensionTables) *HTLCTokenDBExtension { - return &HTLCTokenDBExtension{table: table} +func NewHTLCTokenDBExtension(prefix string) (*HTLCTokenDBExtension, error) { + table, err := getTableNames(prefix) + if err != nil { + return nil, errors.Wrapf(err, "failed getting table names for prefix [%s]", prefix) + } + return &HTLCTokenDBExtension{table: table}, nil } -func (e *HTLCTokenDBExtension) GetSchema() string { +func (e *HTLCTokenDBExtension) GetSchema(string) string { return fmt.Sprintf(` -- Tokens CREATE TABLE IF NOT EXISTS %s ( @@ -95,3 +114,25 @@ func (e *HTLCTokenDBExtension) StoreToken(tx *sql.Tx, tr driver.TokenRecord, own return nil } + +func (e *HTLCTokenDBExtension) DeleteTokens(tx *sql.Tx, deletedBy string, ids ...*token.ID) error { + //TODO implement me + panic("implement me") +} + +func getTableNames(prefix string) (tableNames, error) { + if prefix != "" { + if len(prefix) > 100 { + return tableNames{}, errors.New("table prefix must be shorter than 100 characters") + } + r := regexp.MustCompile("^[a-zA-Z_]+$") + if !r.MatchString(prefix) { + return tableNames{}, errors.New("illegal character in table prefix, only letters and underscores allowed") + } + prefix = strings.ToLower(prefix) + "_" + } + + return tableNames{ + Tokens: fmt.Sprintf("%stokens", prefix), + }, nil +} diff --git a/token/services/selector/sherdlock/manager_test.go b/token/services/selector/sherdlock/manager_test.go index 2e7592b5b..5b206ab29 100644 --- a/token/services/selector/sherdlock/manager_test.go +++ b/token/services/selector/sherdlock/manager_test.go @@ -12,6 +12,7 @@ import ( "time" utils2 "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils" + dbdriver "github.com/hyperledger-labs/fabric-token-sdk/token/services/db/driver" "github.com/hyperledger-labs/fabric-token-sdk/token/services/db/sql" "github.com/hyperledger-labs/fabric-token-sdk/token/services/selector/testutils" _ "github.com/lib/pq" @@ -74,7 +75,9 @@ func createManager(pgConnStr string, backoff time.Duration) (testutils.EnhancedM return nil, err } - tokenDB, err := initDB("postgres", pgConnStr, "test", 10, sql.NewTokenDB) + tokenDB, err := initDB("postgres", pgConnStr, "test", 10, func(db *sql2.DB, tablePrefix string, createSchema bool) (dbdriver.TokenDB, error) { + return sql.NewTokenDB(db, tablePrefix, createSchema) + }) if err != nil { return nil, err } diff --git a/token/services/tokendb/db/memory/memory.go b/token/services/tokendb/db/memory/memory.go index 0f135efb6..339a4b69b 100644 --- a/token/services/tokendb/db/memory/memory.go +++ b/token/services/tokendb/db/memory/memory.go @@ -7,16 +7,20 @@ SPDX-License-Identifier: Apache-2.0 package memory import ( + "database/sql" + "github.com/hyperledger-labs/fabric-token-sdk/token/services/db" dbdriver "github.com/hyperledger-labs/fabric-token-sdk/token/services/db/driver" sqldb "github.com/hyperledger-labs/fabric-token-sdk/token/services/db/sql" - "github.com/hyperledger-labs/fabric-token-sdk/token/services/tokendb/db/sql" + sql2 "github.com/hyperledger-labs/fabric-token-sdk/token/services/tokendb/db/sql" _ "modernc.org/sqlite" ) func NewDriver() db.NamedDriver[dbdriver.TokenDBDriver] { return db.NamedDriver[dbdriver.TokenDBDriver]{ - Name: "memory", - Driver: db.NewMemoryDriver(sql.NewSQLDBOpener(), sqldb.NewTokenDB), + Name: "memory", + Driver: db.NewMemoryDriver(sql2.NewSQLDBOpener(), func(db *sql.DB, tablePrefix string, createSchema bool) (dbdriver.TokenDB, error) { + return sqldb.NewTokenDB(db, tablePrefix, createSchema) + }), } } diff --git a/token/services/tokendb/db/sql/driver.go b/token/services/tokendb/db/sql/driver.go index 302c29696..36304ca7c 100644 --- a/token/services/tokendb/db/sql/driver.go +++ b/token/services/tokendb/db/sql/driver.go @@ -7,6 +7,8 @@ SPDX-License-Identifier: Apache-2.0 package sql import ( + "database/sql" + "github.com/hyperledger-labs/fabric-token-sdk/token/services/db" dbdriver "github.com/hyperledger-labs/fabric-token-sdk/token/services/db/driver" sqldb "github.com/hyperledger-labs/fabric-token-sdk/token/services/db/sql" @@ -24,7 +26,9 @@ func NewSQLDBOpener() *sqldb.DBOpener { func NewDriver() db.NamedDriver[dbdriver.TokenDBDriver] { return db.NamedDriver[dbdriver.TokenDBDriver]{ - Name: "sql", - Driver: db.NewSQLDriver(NewSQLDBOpener(), sqldb.NewTokenDB), + Name: "sql", + Driver: db.NewSQLDriver(NewSQLDBOpener(), func(db *sql.DB, tablePrefix string, createSchema bool) (dbdriver.TokenDB, error) { + return sqldb.NewTokenDB(db, tablePrefix, createSchema) + }), } }