Skip to content

Commit 3260f67

Browse files
author
Jenita
committed
feat: addressed review comments
Signed-off-by: Jenita <jkawan@blinklabs.io>
1 parent 04852d0 commit 3260f67

File tree

9 files changed

+107
-162
lines changed

9 files changed

+107
-162
lines changed

database/models/datum.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ func (Datum) TableName() string {
2727

2828
// PlutusData represents a Plutus data value in the witness set
2929
type PlutusData struct {
30-
ID uint `gorm:"primaryKey"`
31-
TransactionID uint `gorm:"index"`
32-
Data []byte `gorm:"type:bytea"`
30+
ID uint `gorm:"primaryKey"`
31+
TransactionID uint `gorm:"index"`
32+
Data []byte
3333
Transaction *Transaction
3434
}
3535

database/models/models.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ var MigrateModels = []any{
4040
&Redeemer{},
4141
&ResignCommitteeCold{},
4242
&Script{},
43-
&ScriptContent{},
4443
&StakeDelegation{},
4544
&StakeDeregistration{},
4645
&StakeRegistration{},
@@ -53,4 +52,5 @@ var MigrateModels = []any{
5352
&Utxo{},
5453
&VoteDelegation{},
5554
&VoteRegistrationDelegation{},
55+
&WitnessScripts{},
5656
}

database/models/script.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
package models
1616

17-
// Script represents a reference to a script in the witness set
17+
// WitnessScripts represents a reference to a script in the witness set
1818
// Type corresponds to ScriptRefType constants from gouroboros/ledger/common:
1919
// 0=NativeScript (ScriptRefTypeNativeScript)
2020
// 1=PlutusV1 (ScriptRefTypePlutusV1)
@@ -23,15 +23,15 @@ package models
2323
//
2424
// To avoid storing duplicate script data for the same script used in multiple
2525
// transactions, we store only the script hash here. The actual script content
26-
// is stored separately in ScriptContent table, indexed by hash.
27-
type Script struct {
26+
// is stored separately in Script table, indexed by hash.
27+
type WitnessScripts struct {
2828
ID uint `gorm:"primaryKey"`
2929
TransactionID uint `gorm:"index"`
3030
Type uint8 `gorm:"index"` // Script type
3131
ScriptHash []byte `gorm:"index"` // Hash of the script
3232
Transaction *Transaction
3333
}
3434

35-
func (Script) TableName() string {
36-
return "script"
35+
func (WitnessScripts) TableName() string {
36+
return "witness_scripts"
3737
}

database/models/script_content.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@
1414

1515
package models
1616

17-
// ScriptContent represents the content of a script, indexed by its hash
17+
// Script represents the content of a script, indexed by its hash
1818
// This avoids storing duplicate script data when the same script appears
1919
// in multiple transactions
20-
type ScriptContent struct {
20+
type Script struct {
2121
ID uint `gorm:"primaryKey"`
2222
Hash []byte `gorm:"index;unique"` // Script hash
2323
Type uint8 `gorm:"index"` // Script type
2424
Content []byte // Script content
2525
CreatedSlot uint64 // Slot when this script was first seen
2626
}
2727

28-
func (ScriptContent) TableName() string {
29-
return "script_content"
28+
func (Script) TableName() string {
29+
return "script"
3030
}

database/models/transaction.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,18 @@ package models
1616

1717
// Transaction represents a transaction record
1818
type Transaction struct {
19-
Hash []byte `gorm:"uniqueIndex"`
20-
BlockHash []byte `gorm:"index"`
21-
Inputs []Utxo `gorm:"foreignKey:SpentAtTxId;references:Hash"`
22-
Outputs []Utxo `gorm:"foreignKey:TransactionID;references:ID"`
23-
ReferenceInputs []Utxo `gorm:"foreignKey:ReferencedByTxId;references:Hash"`
24-
Collateral []Utxo `gorm:"foreignKey:CollateralByTxId;references:Hash"`
25-
CollateralReturn *Utxo `gorm:"foreignKey:TransactionID;references:ID"`
26-
KeyWitnesses []KeyWitness `gorm:"foreignKey:TransactionID;references:ID"`
27-
Scripts []Script `gorm:"foreignKey:TransactionID;references:ID"`
28-
Redeemers []Redeemer `gorm:"foreignKey:TransactionID;references:ID"`
29-
PlutusData []PlutusData `gorm:"foreignKey:TransactionID;references:ID"`
30-
ID uint `gorm:"primaryKey"`
19+
Hash []byte `gorm:"uniqueIndex"`
20+
BlockHash []byte `gorm:"index"`
21+
Inputs []Utxo `gorm:"foreignKey:SpentAtTxId;references:Hash"`
22+
Outputs []Utxo `gorm:"foreignKey:TransactionID;references:ID"`
23+
ReferenceInputs []Utxo `gorm:"foreignKey:ReferencedByTxId;references:Hash"`
24+
Collateral []Utxo `gorm:"foreignKey:CollateralByTxId;references:Hash"`
25+
CollateralReturn *Utxo `gorm:"foreignKey:TransactionID;references:ID"`
26+
KeyWitnesses []KeyWitness `gorm:"foreignKey:TransactionID;references:ID"`
27+
WitnessScripts []WitnessScripts `gorm:"foreignKey:TransactionID;references:ID"`
28+
Redeemers []Redeemer `gorm:"foreignKey:TransactionID;references:ID"`
29+
PlutusData []PlutusData `gorm:"foreignKey:TransactionID;references:ID"`
30+
ID uint `gorm:"primaryKey"`
3131
Type int
3232
BlockIndex uint32
3333
Metadata []byte

database/models/witness.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ package models
1616

1717
const (
1818
// KeyWitnessTypeVkey represents a Vkey witness
19-
KeyWitnessTypeVkey uint8 = iota
19+
KeyWitnessTypeVkey uint8 = 0
2020
// KeyWitnessTypeBootstrap represents a Bootstrap witness
21-
KeyWitnessTypeBootstrap
21+
KeyWitnessTypeBootstrap uint8 = 1
2222
)
2323

2424
// KeyWitness represents a key witness entry (Vkey or Bootstrap)

database/plugin/metadata/sqlite/script.go

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ import (
2222
"gorm.io/gorm"
2323
)
2424

25-
// GetScriptContent returns the script content by its hash
26-
func (d *MetadataStoreSqlite) GetScriptContent(
25+
// GetScript returns the script content by its hash
26+
func (d *MetadataStoreSqlite) GetScript(
2727
hash lcommon.ScriptHash,
2828
txn *gorm.DB,
29-
) (*models.ScriptContent, error) {
30-
ret := &models.ScriptContent{}
29+
) (*models.Script, error) {
30+
ret := &models.Script{}
3131
if txn == nil {
3232
txn = d.DB()
3333
}
@@ -40,19 +40,3 @@ func (d *MetadataStoreSqlite) GetScriptContent(
4040
}
4141
return ret, nil
4242
}
43-
44-
// GetScriptsByTransaction returns all scripts (references) used in a particular transaction
45-
func (d *MetadataStoreSqlite) GetScriptsByTransaction(
46-
txID uint,
47-
txn *gorm.DB,
48-
) ([]models.Script, error) {
49-
var scripts []models.Script
50-
if txn == nil {
51-
txn = d.DB()
52-
}
53-
result := txn.Where("transaction_id = ?", txID).Find(&scripts)
54-
if result.Error != nil {
55-
return nil, result.Error
56-
}
57-
return scripts, nil
58-
}

database/plugin/metadata/sqlite/transaction.go

Lines changed: 74 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -292,19 +292,17 @@ func (d *MetadataStoreSqlite) SetTransaction(
292292
}
293293
// Extract and save witness set data
294294
// Delete existing witness records to ensure idempotency on retry
295-
if tmpTx.ID != 0 {
296-
if result := txn.Where("transaction_id = ?", tmpTx.ID).Delete(&models.KeyWitness{}); result.Error != nil {
297-
return fmt.Errorf("delete existing key witnesses: %w", result.Error)
298-
}
299-
if result := txn.Where("transaction_id = ?", tmpTx.ID).Delete(&models.Script{}); result.Error != nil {
300-
return fmt.Errorf("delete existing scripts: %w", result.Error)
301-
}
302-
if result := txn.Where("transaction_id = ?", tmpTx.ID).Delete(&models.Redeemer{}); result.Error != nil {
303-
return fmt.Errorf("delete existing redeemers: %w", result.Error)
304-
}
305-
if result := txn.Where("transaction_id = ?", tmpTx.ID).Delete(&models.PlutusData{}); result.Error != nil {
306-
return fmt.Errorf("delete existing plutus data: %w", result.Error)
307-
}
295+
if result := txn.Where("transaction_id = ?", tmpTx.ID).Delete(&models.KeyWitness{}); result.Error != nil {
296+
return fmt.Errorf("delete existing key witnesses: %w", result.Error)
297+
}
298+
if result := txn.Where("transaction_id = ?", tmpTx.ID).Delete(&models.WitnessScripts{}); result.Error != nil {
299+
return fmt.Errorf("delete existing witness scripts: %w", result.Error)
300+
}
301+
if result := txn.Where("transaction_id = ?", tmpTx.ID).Delete(&models.Redeemer{}); result.Error != nil {
302+
return fmt.Errorf("delete existing redeemers: %w", result.Error)
303+
}
304+
if result := txn.Where("transaction_id = ?", tmpTx.ID).Delete(&models.PlutusData{}); result.Error != nil {
305+
return fmt.Errorf("delete existing plutus data: %w", result.Error)
308306
}
309307
ws := tx.Witnesses()
310308
if ws != nil {
@@ -336,108 +334,75 @@ func (d *MetadataStoreSqlite) SetTransaction(
336334
}
337335
}
338336

339-
// Add Native Scripts
340-
for _, script := range ws.NativeScripts() {
341-
scriptHash := script.Hash()
342-
scriptRecord := models.Script{
343-
TransactionID: tmpTx.ID,
344-
Type: uint8(lcommon.ScriptRefTypeNativeScript),
345-
ScriptHash: scriptHash.Bytes(),
346-
}
347-
if result := txn.Create(&scriptRecord); result.Error != nil {
348-
return fmt.Errorf("create native script: %w", result.Error)
349-
}
350-
// Also store the script content separately to avoid duplicates
351-
scriptContent := models.ScriptContent{
352-
Hash: scriptHash.Bytes(),
353-
Type: uint8(lcommon.ScriptRefTypeNativeScript),
354-
Content: script.Cbor(),
355-
CreatedSlot: point.Slot,
356-
}
357-
if result := txn.Clauses(clause.OnConflict{
358-
Columns: []clause.Column{{Name: "hash"}},
359-
DoNothing: true,
360-
}).Create(&scriptContent); result.Error != nil {
361-
return fmt.Errorf("create native script content: %w", result.Error)
337+
// Helper function to process scripts - deduplicates the 4 script type blocks
338+
processScripts := func(scriptType uint8, scripts interface{}) error {
339+
// Common logic for creating script records
340+
createScriptRecords := func(scriptHash lcommon.ScriptHash, content []byte) error {
341+
witnessScript := models.WitnessScripts{
342+
TransactionID: tmpTx.ID,
343+
Type: scriptType,
344+
ScriptHash: scriptHash.Bytes(),
345+
}
346+
if result := txn.Create(&witnessScript); result.Error != nil {
347+
return fmt.Errorf("create witness script: %w", result.Error)
348+
}
349+
scriptContent := models.Script{
350+
Hash: scriptHash.Bytes(),
351+
Type: scriptType,
352+
Content: content,
353+
CreatedSlot: point.Slot,
354+
}
355+
if result := txn.Clauses(clause.OnConflict{
356+
Columns: []clause.Column{{Name: "hash"}},
357+
DoNothing: true,
358+
}).Create(&scriptContent); result.Error != nil {
359+
return fmt.Errorf("create script content: %w", result.Error)
360+
}
361+
return nil
362362
}
363-
}
364363

365-
// Add PlutusV1 Scripts
366-
for _, script := range ws.PlutusV1Scripts() {
367-
scriptHash := script.Hash()
368-
scriptRecord := models.Script{
369-
TransactionID: tmpTx.ID,
370-
Type: uint8(lcommon.ScriptRefTypePlutusV1),
371-
ScriptHash: scriptHash.Bytes(),
372-
}
373-
if result := txn.Create(&scriptRecord); result.Error != nil {
374-
return fmt.Errorf("create plutus v1 script: %w", result.Error)
375-
}
376-
// Also store the script content separately to avoid duplicates
377-
scriptContent := models.ScriptContent{
378-
Hash: scriptHash.Bytes(),
379-
Type: uint8(lcommon.ScriptRefTypePlutusV1),
380-
Content: script.RawScriptBytes(),
381-
CreatedSlot: point.Slot,
382-
}
383-
if result := txn.Clauses(clause.OnConflict{
384-
Columns: []clause.Column{{Name: "hash"}},
385-
DoNothing: true,
386-
}).Create(&scriptContent); result.Error != nil {
387-
return fmt.Errorf("create plutus v1 script content: %w", result.Error)
364+
// Type switch to handle different script types
365+
switch s := scripts.(type) {
366+
case []lcommon.NativeScript:
367+
for _, script := range s {
368+
if err := createScriptRecords(script.Hash(), script.Cbor()); err != nil {
369+
return err
370+
}
371+
}
372+
case []lcommon.PlutusV1Script:
373+
for _, script := range s {
374+
if err := createScriptRecords(script.Hash(), script.RawScriptBytes()); err != nil {
375+
return err
376+
}
377+
}
378+
case []lcommon.PlutusV2Script:
379+
for _, script := range s {
380+
if err := createScriptRecords(script.Hash(), script.RawScriptBytes()); err != nil {
381+
return err
382+
}
383+
}
384+
case []lcommon.PlutusV3Script:
385+
for _, script := range s {
386+
if err := createScriptRecords(script.Hash(), script.RawScriptBytes()); err != nil {
387+
return err
388+
}
389+
}
388390
}
391+
return nil
389392
}
390393

391-
// Add PlutusV2 Scripts
392-
for _, script := range ws.PlutusV2Scripts() {
393-
scriptHash := script.Hash()
394-
scriptRecord := models.Script{
395-
TransactionID: tmpTx.ID,
396-
Type: uint8(lcommon.ScriptRefTypePlutusV2),
397-
ScriptHash: scriptHash.Bytes(),
398-
}
399-
if result := txn.Create(&scriptRecord); result.Error != nil {
400-
return fmt.Errorf("create plutus v2 script: %w", result.Error)
401-
}
402-
// Also store the script content separately to avoid duplicates
403-
scriptContent := models.ScriptContent{
404-
Hash: scriptHash.Bytes(),
405-
Type: uint8(lcommon.ScriptRefTypePlutusV2),
406-
Content: script.RawScriptBytes(),
407-
CreatedSlot: point.Slot,
408-
}
409-
if result := txn.Clauses(clause.OnConflict{
410-
Columns: []clause.Column{{Name: "hash"}},
411-
DoNothing: true,
412-
}).Create(&scriptContent); result.Error != nil {
413-
return fmt.Errorf("create plutus v2 script content: %w", result.Error)
414-
}
394+
// Process all script types
395+
if err := processScripts(uint8(lcommon.ScriptRefTypeNativeScript), ws.NativeScripts()); err != nil {
396+
return err
415397
}
416-
417-
// Add PlutusV3 Scripts
418-
for _, script := range ws.PlutusV3Scripts() {
419-
scriptHash := script.Hash()
420-
scriptRecord := models.Script{
421-
TransactionID: tmpTx.ID,
422-
Type: uint8(lcommon.ScriptRefTypePlutusV3),
423-
ScriptHash: scriptHash.Bytes(),
424-
}
425-
if result := txn.Create(&scriptRecord); result.Error != nil {
426-
return fmt.Errorf("create plutus v3 script: %w", result.Error)
427-
}
428-
// Also store the script content separately to avoid duplicates
429-
scriptContent := models.ScriptContent{
430-
Hash: scriptHash.Bytes(),
431-
Type: uint8(lcommon.ScriptRefTypePlutusV3),
432-
Content: script.RawScriptBytes(),
433-
CreatedSlot: point.Slot,
434-
}
435-
if result := txn.Clauses(clause.OnConflict{
436-
Columns: []clause.Column{{Name: "hash"}},
437-
DoNothing: true,
438-
}).Create(&scriptContent); result.Error != nil {
439-
return fmt.Errorf("create plutus v3 script content: %w", result.Error)
440-
}
398+
if err := processScripts(uint8(lcommon.ScriptRefTypePlutusV1), ws.PlutusV1Scripts()); err != nil {
399+
return err
400+
}
401+
if err := processScripts(uint8(lcommon.ScriptRefTypePlutusV2), ws.PlutusV2Scripts()); err != nil {
402+
return err
403+
}
404+
if err := processScripts(uint8(lcommon.ScriptRefTypePlutusV3), ws.PlutusV3Scripts()); err != nil {
405+
return err
441406
}
442407

443408
// Add PlutusData (Datums)

database/plugin/metadata/store.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,10 @@ type MetadataStore interface {
8383
[]byte, // hash
8484
*gorm.DB,
8585
) (*models.Transaction, error)
86-
GetScriptContent(
86+
GetScript(
8787
lcommon.ScriptHash,
8888
*gorm.DB,
89-
) (*models.ScriptContent, error)
90-
GetScriptsByTransaction(
91-
uint, // txID
92-
*gorm.DB,
93-
) ([]models.Script, error)
89+
) (*models.Script, error)
9490

9591
SetBlockNonce(
9692
[]byte, // blockHash

0 commit comments

Comments
 (0)