feat: batch get outpoint values

This commit is contained in:
Gaze
2024-06-10 17:33:09 +07:00
parent 0172f036fb
commit f4025e0f15
2 changed files with 44 additions and 16 deletions

View File

@@ -20,7 +20,7 @@ import (
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
) )
func (p *Processor) processInscriptionTx(ctx context.Context, tx *types.Transaction, blockHeader types.BlockHeader, transfersInOutPoints map[wire.OutPoint]map[ordinals.SatPoint][]*entity.InscriptionTransfer) error { func (p *Processor) processInscriptionTx(ctx context.Context, tx *types.Transaction, blockHeader types.BlockHeader, transfersInOutPoints map[wire.OutPoint]map[ordinals.SatPoint][]*entity.InscriptionTransfer, outpointValues map[wire.OutPoint]uint64) error {
ctx = logger.WithContext(ctx, slogx.String("tx_hash", tx.TxHash.String())) ctx = logger.WithContext(ctx, slogx.String("tx_hash", tx.TxHash.String()))
envelopes := ordinals.ParseEnvelopesFromTx(tx) envelopes := ordinals.ParseEnvelopesFromTx(tx)
inputOutPoints := lo.Map(tx.TxIn, func(txIn *types.TxIn, _ int) wire.OutPoint { inputOutPoints := lo.Map(tx.TxIn, func(txIn *types.TxIn, _ int) wire.OutPoint {
@@ -31,13 +31,17 @@ func (p *Processor) processInscriptionTx(ctx context.Context, tx *types.Transact
}) })
// cache outpoint values for future blocks // cache outpoint values for future blocks
for outIndex, txOut := range tx.TxOut { for outIndex, txOut := range tx.TxOut {
p.outPointValueCache.Add(wire.OutPoint{ outPoint := wire.OutPoint{
Hash: tx.TxHash, Hash: tx.TxHash,
Index: uint32(outIndex), Index: uint32(outIndex),
}, uint64(txOut.Value)) }
p.outPointValueCache.Add(outPoint, uint64(txOut.Value))
outpointValues[outPoint] = uint64(txOut.Value)
} }
outPointsWithTransfers := lo.Keys(transfersInOutPoints)
txContainsTransfers := len(lo.Intersect(inputOutPoints, outPointsWithTransfers)) > 0
isCoinbase := tx.TxIn[0].PreviousOutTxHash.IsEqual(&chainhash.Hash{}) isCoinbase := tx.TxIn[0].PreviousOutTxHash.IsEqual(&chainhash.Hash{})
if len(envelopes) == 0 && len(transfersInOutPoints) == 0 && !isCoinbase { if len(envelopes) == 0 && !txContainsTransfers && !isCoinbase {
// no inscription activity, skip // no inscription activity, skip
return nil return nil
} }
@@ -50,10 +54,6 @@ func (p *Processor) processInscriptionTx(ctx context.Context, tx *types.Transact
count int count int
}) })
idCounter := uint32(0) idCounter := uint32(0)
inputValues, err := p.getOutPointValues(ctx, inputOutPoints)
if err != nil {
return errors.Wrap(err, "failed to get outpoint values")
}
for i, input := range tx.TxIn { for i, input := range tx.TxIn {
// skip coinbase inputs since there can't be an inscription in coinbase // skip coinbase inputs since there can't be an inscription in coinbase
if input.PreviousOutTxHash.IsEqual(&chainhash.Hash{}) { if input.PreviousOutTxHash.IsEqual(&chainhash.Hash{}) {
@@ -64,7 +64,7 @@ func (p *Processor) processInscriptionTx(ctx context.Context, tx *types.Transact
Hash: input.PreviousOutTxHash, Hash: input.PreviousOutTxHash,
Index: input.PreviousOutIndex, Index: input.PreviousOutIndex,
} }
inputValue := inputValues[inputOutPoint] inputValue := outpointValues[inputOutPoint]
transfersInOutPoint := transfersInOutPoints[inputOutPoint] transfersInOutPoint := transfersInOutPoints[inputOutPoint]
for satPoint, transfers := range transfersInOutPoint { for satPoint, transfers := range transfersInOutPoint {

View File

@@ -22,12 +22,14 @@ import (
func (p *Processor) Process(ctx context.Context, blocks []*types.Block) error { func (p *Processor) Process(ctx context.Context, blocks []*types.Block) error {
for _, block := range blocks { for _, block := range blocks {
ctx = logger.WithContext(ctx, slogx.Uint64("height", uint64(block.Header.Height))) ctx = logger.WithContext(ctx, slogx.Uint64("height", uint64(block.Header.Height)))
logger.DebugContext(ctx, "Processing new block")
p.blockReward = p.getBlockSubsidy(uint64(block.Header.Height)) p.blockReward = p.getBlockSubsidy(uint64(block.Header.Height))
p.flotsamsSentAsFee = make([]*entity.Flotsam, 0) p.flotsamsSentAsFee = make([]*entity.Flotsam, 0)
// put coinbase tx (first tx) at the end of block
transactions := append(block.Transactions[1:], block.Transactions[0])
var inputOutPoints []wire.OutPoint var inputOutPoints []wire.OutPoint
for _, tx := range block.Transactions { for _, tx := range transactions {
for _, txIn := range tx.TxIn { for _, txIn := range tx.TxIn {
if txIn.PreviousOutTxHash == (chainhash.Hash{}) { if txIn.PreviousOutTxHash == (chainhash.Hash{}) {
// skip coinbase input // skip coinbase input
@@ -39,16 +41,42 @@ func (p *Processor) Process(ctx context.Context, blocks []*types.Block) error {
}) })
} }
} }
// pre-fetch inscriptions in outpoints
transfersInOutPoints, err := p.getInscriptionTransfersInOutPoints(ctx, inputOutPoints) transfersInOutPoints, err := p.getInscriptionTransfersInOutPoints(ctx, inputOutPoints)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to get inscriptions in outpoints") return errors.Wrap(err, "failed to get inscriptions in outpoints")
} }
logger.DebugContext(ctx, "Got inscriptions in outpoints", slogx.Int("countOutPoints", len(transfersInOutPoints))) // pre-fetch outpoint values for transactions with inscriptions/envelopes
outPointsToFetchValues := make([]wire.OutPoint, 0)
// put coinbase tx (first tx) at the end of block
transactions := append(block.Transactions[1:], block.Transactions[0])
for _, tx := range transactions { for _, tx := range transactions {
if err := p.processInscriptionTx(ctx, tx, block.Header, transfersInOutPoints); err != nil { txInputOutPoints := lo.Map(tx.TxIn, func(txIn *types.TxIn, _ int) wire.OutPoint {
return wire.OutPoint{
Hash: txIn.PreviousOutTxHash,
Index: txIn.PreviousOutIndex,
}
})
envelopes := ordinals.ParseEnvelopesFromTx(tx)
outPointsWithTransfers := lo.Keys(transfersInOutPoints)
txContainsTransfers := len(lo.Intersect(txInputOutPoints, outPointsWithTransfers)) > 0
isCoinbase := tx.TxIn[0].PreviousOutTxHash.IsEqual(&chainhash.Hash{})
if len(envelopes) == 0 && !txContainsTransfers && !isCoinbase {
// no inscription activity, skip tx
continue
}
outPointsToFetchValues = append(outPointsToFetchValues, lo.Map(tx.TxIn, func(txIn *types.TxIn, _ int) wire.OutPoint {
return wire.OutPoint{
Hash: txIn.PreviousOutTxHash,
Index: txIn.PreviousOutIndex,
}
})...)
}
outPointValues, err := p.getOutPointValues(ctx, outPointsToFetchValues)
if err != nil {
return errors.Wrap(err, "failed to get input values")
}
for _, tx := range transactions {
if err := p.processInscriptionTx(ctx, tx, block.Header, transfersInOutPoints, outPointValues); err != nil {
return errors.Wrap(err, "failed to process tx") return errors.Wrap(err, "failed to process tx")
} }
} }