Skip to content

Commit

Permalink
Refactor matching (#487)
Browse files Browse the repository at this point in the history
  • Loading branch information
NicolasDorier authored Nov 26, 2024
1 parent a201004 commit 88f7d82
Show file tree
Hide file tree
Showing 9 changed files with 178 additions and 180 deletions.
1 change: 0 additions & 1 deletion NBXplorer.Tests/TrackedTransactionBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ public TrackedTransaction Build()
{
var tx = new TrackedTransaction(new TrackedTransactionKey(_TransactionId, _BlockId, true), _Parent._TrackedSource, null as Coin[], null)
{
Inserted = _TimeStamp,
FirstSeen = _TimeStamp
};
foreach (var input in _Inputs)
Expand Down
6 changes: 3 additions & 3 deletions NBXplorer.Tests/UnitTest1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3395,7 +3395,7 @@ uint256 ToUint256(byte o)

bool IsEqual(AnnotatedTransaction tx, TrackedTransactionBuilder.TransactionContext ctx)
{
return tx.Record.TransactionHash == ctx._TransactionId && tx.Record.Inserted == ctx._TimeStamp;
return tx.Record.TransactionHash == ctx._TransactionId && tx.Record.FirstSeen == ctx._TimeStamp;
}

for (int iii = 0; iii < 100; iii++)
Expand Down Expand Up @@ -3440,8 +3440,8 @@ bool IsEqual(AnnotatedTransaction tx, TrackedTransactionBuilder.TransactionConte
Assert.Null(collection.GetByTxId(_17b3b3._TransactionId));

var tx = collection.GetByTxId(ab3922dup._TransactionId);
Assert.Equal(ab3922._TimeStamp, tx.Record.Inserted);
Assert.NotEqual(ab3922dup._TimeStamp, tx.Record.Inserted);
Assert.Equal(ab3922._TimeStamp, tx.Record.FirstSeen);
Assert.NotEqual(ab3922dup._TimeStamp, tx.Record.FirstSeen);
}

var lastBlock = ToUint256(10);
Expand Down
49 changes: 7 additions & 42 deletions NBXplorer/Backend/DbConnectionHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,46 +54,11 @@ public static void Register(NpgsqlDataSourceBuilder dsBuilder)
dsBuilder.MapComposite<OutpointRaw>("outpoint");
dsBuilder.MapComposite<Repository.DescriptorScriptInsert>("nbxv1_ds");
}

public Task<bool> FetchMatches(IEnumerable<Transaction> txs, SlimChainedBlock slimBlock, Money? minUtxoValue)
public async Task<bool> FetchMatches(MatchQuery matchQuery)
{
var outCount = txs.Select(t => t.Outputs.Count).Sum();
List<DbConnectionHelper.NewOut> outs = new List<DbConnectionHelper.NewOut>(outCount);
var inCount = txs.Select(t => t.Inputs.Count).Sum();
List<DbConnectionHelper.NewIn> ins = new List<DbConnectionHelper.NewIn>(inCount);
foreach (var tx in txs)
{
if (!tx.IsCoinBase)
{
int i = 0;
foreach (var input in tx.Inputs)
{
ins.Add(new DbConnectionHelper.NewIn(tx.GetHash(), i, input.PrevOut.Hash, (int)input.PrevOut.N));
i++;
}
}
int io = -1;
foreach (var output in tx.Outputs)
{
io++;
if (minUtxoValue != null && output.Value < minUtxoValue)
continue;
outs.Add(new DbConnectionHelper.NewOut(tx.GetHash(), io, output.ScriptPubKey, output.Value));
}
}

return FetchMatches(outs, ins);
}
public async Task<bool> FetchMatches(IEnumerable<NewOut>? newOuts, IEnumerable<NewIn>? newIns)
{
newOuts ??= Array.Empty<NewOut>();
newIns ??= Array.Empty<NewIn>();
newOuts.TryGetNonEnumeratedCount(out int outCount);
newIns.TryGetNonEnumeratedCount(out int inCount);

var outs = new List<NewOutRaw>(outCount);
var ins = new List<NewInRaw>(inCount);
foreach (var o in newOuts)
var outs = new List<NewOutRaw>(matchQuery.Outs.Count);
var ins = new List<NewInRaw>(matchQuery.Ins.Count);
foreach (var o in matchQuery.Outs)
{
long value;
string assetId;
Expand All @@ -114,7 +79,7 @@ public async Task<bool> FetchMatches(IEnumerable<NewOut>? newOuts, IEnumerable<N
}
outs.Add(new NewOutRaw(o.txId.ToString(), o.idx, o.script.ToHex(), value, assetId));
}
foreach (var ni in newIns)
foreach (var ni in matchQuery.Ins)
{
ins.Add(new NewInRaw(ni.txId.ToString(), ni.idx, ni.spentTxId.ToString(), ni.spentIdx));
}
Expand All @@ -127,9 +92,9 @@ public async Task<bool> FetchMatches(IEnumerable<NewOut>? newOuts, IEnumerable<N
await Connection.QueryAsync<int>("fetch_matches", parameters, commandType: CommandType.StoredProcedure);
return parameters.Get<bool>("has_match");
}
public record SaveTransactionRecord(Transaction? Transaction, uint256? Id, uint256? BlockId, int? BlockIndex, long? BlockHeight, bool Immature, DateTimeOffset? SeenAt)
public record SaveTransactionRecord(Transaction? Transaction, uint256 Id, uint256? BlockId, int? BlockIndex, long? BlockHeight, bool Immature, DateTimeOffset SeenAt)
{
public static SaveTransactionRecord Create(TrackedTransaction t) => new SaveTransactionRecord(t.Transaction, t.TransactionHash, t.BlockHash, t.BlockIndex, t.BlockHeight, t.IsCoinBase, new DateTimeOffset?(t.FirstSeen));
public static SaveTransactionRecord Create(TrackedTransaction t) => new SaveTransactionRecord(t.Transaction, t.TransactionHash, t.BlockHash, t.BlockIndex, t.BlockHeight, t.IsCoinBase, t.FirstSeen);
public static SaveTransactionRecord Create(SlimChainedBlock slimBlock, Transaction tx, int? blockIndex, DateTimeOffset now) => new SaveTransactionRecord(
tx,
tx.GetHash(),
Expand Down
84 changes: 84 additions & 0 deletions NBXplorer/Backend/MatchQuery.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#nullable enable
using NBitcoin;
using System.Collections.Generic;
using System.Linq;

namespace NBXplorer.Backend
{
public class MatchQuery
{
public MatchQuery(List<DbConnectionHelper.NewIn> ins, List<DbConnectionHelper.NewOut> outs)
{
Ins = ins;
Outs = outs;
}
public List<DbConnectionHelper.NewIn> Ins { get; }
public List<DbConnectionHelper.NewOut> Outs { get; }

public static MatchQuery FromTransactions(IEnumerable<TrackedTransaction> txs, Money? minUtxoValue)
{
var outCount = txs.Select(t => t.ReceivedCoins.Count).Sum();
var inCount = txs.Select(t => t.SpentOutpoints.Count).Sum();
List<DbConnectionHelper.NewOut> outs = new List<DbConnectionHelper.NewOut>(outCount);
List<DbConnectionHelper.NewIn> ins = new List<DbConnectionHelper.NewIn>(inCount);
foreach (var tx in txs)
{
if (!tx.IsCoinBase)
{
foreach (var input in tx.SpentOutpoints)
{
ins.Add(new DbConnectionHelper.NewIn(
tx.TransactionHash,
input.InputIndex,
input.Outpoint.Hash,
(int)input.Outpoint.N
));
}
}

foreach (var output in tx.ReceivedCoins)
{
if (minUtxoValue != null && (Money)output.Amount < minUtxoValue)
continue;
outs.Add(new DbConnectionHelper.NewOut(
tx.TransactionHash,
(int)output.Outpoint.N,
output.TxOut.ScriptPubKey,
(Money)output.Amount
));
}
}
return new MatchQuery(ins, outs);
}

public static MatchQuery FromTransactions(IEnumerable<Transaction> txs, Money? minUtxoValue)
{
var outCount = txs.Select(t => t.Outputs.Count).Sum();
List<DbConnectionHelper.NewOut> outs = new List<DbConnectionHelper.NewOut>(outCount);
var inCount = txs.Select(t => t.Inputs.Count).Sum();
List<DbConnectionHelper.NewIn> ins = new List<DbConnectionHelper.NewIn>(inCount);
foreach (var tx in txs)
{
var hash = tx.GetHash();
if (!tx.IsCoinBase)
{
int i = 0;
foreach (var input in tx.Inputs)
{
ins.Add(new DbConnectionHelper.NewIn(hash, i, input.PrevOut.Hash, (int)input.PrevOut.N));
i++;
}
}
int io = -1;
foreach (var output in tx.Outputs)
{
io++;
if (minUtxoValue != null && output.Value < minUtxoValue)
continue;
outs.Add(new DbConnectionHelper.NewOut(hash, io, output.ScriptPubKey, output.Value));
}
}
return new MatchQuery(ins, outs);
}
}
}
Loading

0 comments on commit 88f7d82

Please sign in to comment.