Skip to content

Commit 62bd8c2

Browse files
committed
fix(database): store produced utxos
Signed-off-by: Chris Gianelloni <wolf31o2@blinklabs.io>
1 parent a20af6e commit 62bd8c2

File tree

2 files changed

+55
-16
lines changed

2 files changed

+55
-16
lines changed

database/plugin/metadata/sqlite/transaction.go

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -176,16 +176,35 @@ func (d *MetadataStoreSqlite) SetTransaction(
176176
tmpTx.Metadata = tmpMetadata
177177
}
178178
collateralReturn := tx.CollateralReturn()
179+
// For invalid transactions with collateral returns, fix indices via CBOR matching
180+
// since Produced() uses enumerated indices rather than real transaction indices
181+
var realIndexMap map[lcommon.Blake2b256]uint32
182+
if !tx.IsValid() && collateralReturn != nil {
183+
realIndexMap = make(map[lcommon.Blake2b256]uint32)
184+
for idx, out := range tx.Outputs() {
185+
if out != nil && idx <= int(^uint32(0)) {
186+
// Hash CBOR for efficient map key
187+
outputHash := lcommon.NewBlake2b256(out.Cbor())
188+
//nolint:gosec // G115: idx bounds already checked above
189+
realIndexMap[outputHash] = uint32(idx)
190+
}
191+
}
192+
}
179193
for _, utxo := range tx.Produced() {
180194
if collateralReturn != nil && utxo.Output == collateralReturn {
181-
utxo := models.UtxoLedgerToModel(utxo, point.Slot)
182-
tmpTx.CollateralReturn = &utxo
195+
m := models.UtxoLedgerToModel(utxo, point.Slot)
196+
// Fix collateral return index for invalid transactions
197+
if realIndexMap != nil && m.Cbor != nil {
198+
outputHash := lcommon.NewBlake2b256(m.Cbor)
199+
if realIdx, ok := realIndexMap[outputHash]; ok {
200+
m.OutputIdx = realIdx
201+
}
202+
}
203+
tmpTx.CollateralReturn = &m
183204
continue
184205
}
185-
tmpTx.Outputs = append(
186-
tmpTx.Outputs,
187-
models.UtxoLedgerToModel(utxo, point.Slot),
188-
)
206+
m := models.UtxoLedgerToModel(utxo, point.Slot)
207+
tmpTx.Outputs = append(tmpTx.Outputs, m)
189208
}
190209
result := txn.Clauses(clause.OnConflict{
191210
Columns: []clause.Column{{Name: "hash"}}, // unique txn hash

database/transaction.go

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,38 @@ func (d *Database) SetTransaction(
3434
txn = d.Transaction(false)
3535
defer txn.Commit() //nolint:errcheck
3636
}
37-
if tx.IsValid() {
38-
for _, utxo := range tx.Produced() {
39-
// Add UTxO to blob DB
40-
key := UtxoBlobKey(
41-
utxo.Id.Id().Bytes(),
42-
utxo.Id.Index(),
43-
)
44-
err := txn.Blob().Set(key, utxo.Output.Cbor())
45-
if err != nil {
46-
return err
37+
// Build index map for invalid transactions with collateral returns
38+
var realIndexMap map[lcommon.Blake2b256]uint32
39+
collateralReturn := tx.CollateralReturn()
40+
if !tx.IsValid() && collateralReturn != nil {
41+
realIndexMap = make(map[lcommon.Blake2b256]uint32)
42+
for idx, out := range tx.Outputs() {
43+
if out != nil && idx <= int(^uint32(0)) {
44+
outputHash := lcommon.NewBlake2b256(out.Cbor())
45+
//nolint:gosec // G115: idx bounds already checked above
46+
realIndexMap[outputHash] = uint32(idx)
47+
}
48+
}
49+
}
50+
// Always store Produced UTxOs (outputs or collateral return)
51+
for _, utxo := range tx.Produced() {
52+
// For invalid transactions, use real index from CBOR matching
53+
outputIdx := utxo.Id.Index()
54+
if realIndexMap != nil {
55+
outputHash := lcommon.NewBlake2b256(utxo.Output.Cbor())
56+
if realIdx, ok := realIndexMap[outputHash]; ok {
57+
outputIdx = realIdx
4758
}
4859
}
60+
// Add UTxO to blob DB
61+
key := UtxoBlobKey(
62+
utxo.Id.Id().Bytes(),
63+
outputIdx,
64+
)
65+
err := txn.Blob().Set(key, utxo.Output.Cbor())
66+
if err != nil {
67+
return err
68+
}
4969
}
5070
err := d.metadata.SetTransaction(
5171
tx,

0 commit comments

Comments
 (0)