Skip to content

Commit

Permalink
Only return a single block where a tx was mined (found by the utxo in…
Browse files Browse the repository at this point in the history
…dexer) (hemilabs#269)
  • Loading branch information
marcopeereboom authored Oct 1, 2024
1 parent 1cd18e2 commit cb9e8d1
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 39 deletions.
6 changes: 2 additions & 4 deletions cmd/hemictl/hemictl.go
Original file line number Diff line number Diff line change
Expand Up @@ -453,13 +453,11 @@ func tbcdb() error {
return fmt.Errorf("chainhash: %w", err)
}

bh, err := s.DB().BlocksByTxId(ctx, chtxid)
bh, err := s.DB().BlockByTxId(ctx, chtxid)
if err != nil {
return fmt.Errorf("block by txid: %w", err)
}
for k := range bh {
fmt.Printf("%v\n", bh[k])
}
fmt.Printf("%v\n", bh)

case "txbyid":
txid := args["txid"]
Expand Down
2 changes: 1 addition & 1 deletion database/tbcd/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ type Database interface {
// Transactions
BlockUtxoUpdate(ctx context.Context, direction int, utxos map[Outpoint]CacheOutput) error
BlockTxUpdate(ctx context.Context, direction int, txs map[TxKey]*TxValue) error
BlocksByTxId(ctx context.Context, txId *chainhash.Hash) ([]*chainhash.Hash, error)
BlockByTxId(ctx context.Context, txId *chainhash.Hash) (*chainhash.Hash, error)
SpentOutputsByTxId(ctx context.Context, txId *chainhash.Hash) ([]SpentInfo, error)

// ScriptHash returns the sha256 of PkScript for the provided outpoint.
Expand Down
16 changes: 10 additions & 6 deletions database/tbcd/level/level.go
Original file line number Diff line number Diff line change
Expand Up @@ -766,9 +766,9 @@ func (l *ldb) BlockByHash(ctx context.Context, hash *chainhash.Hash) (*btcutil.B
return b, nil
}

func (l *ldb) BlocksByTxId(ctx context.Context, txId *chainhash.Hash) ([]*chainhash.Hash, error) {
log.Tracef("BlocksByTxId")
defer log.Tracef("BlocksByTxId exit")
func (l *ldb) BlockByTxId(ctx context.Context, txId *chainhash.Hash) (*chainhash.Hash, error) {
log.Tracef("BlockByTxId")
defer log.Tracef("BlockByTxId exit")

blocks := make([]*chainhash.Hash, 0, 2)
txDB := l.pool[level.TransactionsDB]
Expand All @@ -787,11 +787,15 @@ func (l *ldb) BlocksByTxId(ctx context.Context, txId *chainhash.Hash) ([]*chainh
if err := it.Error(); err != nil {
return nil, fmt.Errorf("blocks by id iterator: %w", err)
}
if len(blocks) == 0 {
switch len(blocks) {
case 0:
return nil, database.NotFoundError(fmt.Sprintf("tx not found: %v", txId))
case 1:
return blocks[0], nil
default:
panic(fmt.Sprintf("invalid blocks count %v: %v",
len(blocks), spew.Sdump(blocks)))
}

return blocks, nil
}

func (l *ldb) SpentOutputsByTxId(ctx context.Context, txId *chainhash.Hash) ([]tbcd.SpentInfo, error) {
Expand Down
13 changes: 3 additions & 10 deletions service/tbc/crawler.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,18 +301,11 @@ func (s *Server) scriptValue(ctx context.Context, op tbcd.Outpoint) ([]byte, int
txIndex := op.TxIndex()

// Find block hashes
blockHashes, err := s.db.BlocksByTxId(ctx, txId)
blockHash, err := s.db.BlockByTxId(ctx, txId)
if err != nil {
return nil, 0, fmt.Errorf("blocks by txid: %w", err)
return nil, 0, fmt.Errorf("block by txid: %w", err)
}
// Note that we may have more than one block hash however since the
// TxID is generated from the actual Tx the script hash and value
// should be identical and thus we can return the values from the first
// block found.
if len(blockHashes) == 0 {
return nil, 0, errors.New("script value: no block hashes")
}
b, err := s.db.BlockByHash(ctx, blockHashes[0])
b, err := s.db.BlockByHash(ctx, blockHash)
if err != nil {
return nil, 0, fmt.Errorf("block by hash: %w", err)
}
Expand Down
25 changes: 7 additions & 18 deletions service/tbc/tbc.go
Original file line number Diff line number Diff line change
Expand Up @@ -1778,28 +1778,17 @@ func (s *Server) TxById(ctx context.Context, txId *chainhash.Hash) (*wire.MsgTx,
log.Tracef("TxById")
defer log.Tracef("TxById exit")

blockHashes, err := s.db.BlocksByTxId(ctx, txId)
blockHash, err := s.db.BlockByTxId(ctx, txId)
if err != nil {
return nil, err
}

if len(blockHashes) > 1 {
panic("fix me blockhashes len")
block, err := s.db.BlockByHash(ctx, blockHash)
if err != nil {
return nil, err
}

// XXX investigate if this is indeed correct. As it is written now it
// returns the first block the tx exists in. This however must be the
// canonical block. This function must also return the blockhash.

for _, blockHash := range blockHashes {
block, err := s.db.BlockByHash(ctx, blockHash)
if err != nil {
return nil, err
}
for _, tx := range block.Transactions() {
if tx.Hash().IsEqual(txId) {
return tx.MsgTx(), nil
}
for _, tx := range block.Transactions() {
if tx.Hash().IsEqual(txId) {
return tx.MsgTx(), nil
}
}

Expand Down

0 comments on commit cb9e8d1

Please sign in to comment.