Skip to content

Commit 19ebe52

Browse files
committed
rpc: surface purged asset set from validateInputAssets
We will later make use of the purged asset set at validateInputAssets callsites.
1 parent 07434e7 commit 19ebe52

File tree

1 file changed

+72
-62
lines changed

1 file changed

+72
-62
lines changed

rpcserver.go

Lines changed: 72 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -2687,7 +2687,8 @@ func (r *rpcServer) CommitVirtualPsbts(ctx context.Context,
26872687
// Make sure the assets given fully satisfy the input commitments.
26882688
allPackets := append([]*tappsbt.VPacket{}, activePackets...)
26892689
allPackets = append(allPackets, passivePackets...)
2690-
err = r.validateInputAssets(ctx, pkt, allPackets)
2690+
purgedAssets := r.collectPurgedAssets(ctx, allPackets)
2691+
err = r.validateInputAssets(ctx, pkt, allPackets, purgedAssets)
26912692
if err != nil {
26922693
return nil, fmt.Errorf("error validating input assets: %w", err)
26932694
}
@@ -2877,10 +2878,77 @@ func (r *rpcServer) CommitVirtualPsbts(ctx context.Context,
28772878
return response, nil
28782879
}
28792880

2881+
// collectPurgedAssets gathers the assets that are being purged for each input
2882+
// commitment across all virtual packets.
2883+
func (r *rpcServer) collectPurgedAssets(ctx context.Context,
2884+
vPackets []*tappsbt.VPacket) map[wire.OutPoint][]*asset.Asset {
2885+
2886+
purgedAssetsDeDup := make(map[wire.OutPoint]map[[32]byte]*asset.Asset)
2887+
for _, vPkt := range vPackets {
2888+
for _, vIn := range vPkt.Inputs {
2889+
inputAsset := vIn.Asset()
2890+
outpoint := vIn.PrevID.OutPoint
2891+
2892+
input, err := r.cfg.AssetStore.FetchCommitment(
2893+
ctx, inputAsset.ID(), outpoint,
2894+
inputAsset.GroupKey, &inputAsset.ScriptKey,
2895+
true,
2896+
)
2897+
if err != nil {
2898+
// If we can't fetch the input commitment, it
2899+
// means this input asset isn't ours. We cannot
2900+
// find out if there were any purged assets in
2901+
// the commitment, so we just rely on all assets
2902+
// being present. If some purged assets are
2903+
// missing, then the anchor input equality check
2904+
// further down will fail.
2905+
rpcsLog.Warnf("Could not fetch input "+
2906+
"commitment for outpoint %v: %v",
2907+
outpoint, err)
2908+
2909+
continue
2910+
}
2911+
2912+
assetsToPurge := tapsend.ExtractUnSpendable(
2913+
input.Commitment,
2914+
)
2915+
if len(assetsToPurge) == 0 {
2916+
continue
2917+
}
2918+
2919+
assetMap := purgedAssetsDeDup[outpoint]
2920+
if assetMap == nil {
2921+
assetMap = make(map[[32]byte]*asset.Asset)
2922+
purgedAssetsDeDup[outpoint] = assetMap
2923+
}
2924+
2925+
for _, a := range assetsToPurge {
2926+
key := a.AssetCommitmentKey()
2927+
assetMap[key] = a
2928+
}
2929+
}
2930+
}
2931+
2932+
// With the assets de-duplicated by their asset commitment key, we can
2933+
// now collect them grouped by input outpoint.
2934+
purgedAssets := make(map[wire.OutPoint][]*asset.Asset)
2935+
for outpoint, assets := range purgedAssetsDeDup {
2936+
for key := range assets {
2937+
purgedAssets[outpoint] = append(
2938+
purgedAssets[outpoint], assets[key],
2939+
)
2940+
}
2941+
}
2942+
2943+
return purgedAssets
2944+
}
2945+
28802946
// validateInputAssets makes sure that the input assets are correct and their
28812947
// combined commitments match the inputs of the BTC level anchor transaction.
2948+
// The purgedAssets map contains the commitment leftovers per anchor input.
28822949
func (r *rpcServer) validateInputAssets(ctx context.Context,
2883-
btcPkt *psbt.Packet, vPackets []*tappsbt.VPacket) error {
2950+
btcPkt *psbt.Packet, vPackets []*tappsbt.VPacket,
2951+
purgedAssets map[wire.OutPoint][]*asset.Asset) error {
28842952

28852953
err := tapsend.ValidateVPacketVersions(vPackets)
28862954
if err != nil {
@@ -2939,65 +3007,6 @@ func (r *rpcServer) validateInputAssets(ctx context.Context,
29393007
}
29403008
}
29413009

2942-
// We also want to make sure we actually have the assets that are being
2943-
// spent in our database. We fetch the input commitments of all packets
2944-
// to asset that. And while we're doing that, we also extract all the
2945-
// pruned assets that are not re-created in the outputs, which we need
2946-
// for the final validation. We de-duplicate the pruned assets in a
2947-
// temporary map keyed by input outpoint and the asset commitment key.
2948-
purgedAssetsDeDup := make(map[wire.OutPoint]map[[32]byte]*asset.Asset)
2949-
for _, vPkt := range vPackets {
2950-
for _, vIn := range vPkt.Inputs {
2951-
inputAsset := vIn.Asset()
2952-
outpoint := vIn.PrevID.OutPoint
2953-
2954-
input, err := r.cfg.AssetStore.FetchCommitment(
2955-
ctx, inputAsset.ID(), outpoint,
2956-
inputAsset.GroupKey, &inputAsset.ScriptKey,
2957-
true,
2958-
)
2959-
if err != nil {
2960-
// If we can't fetch the input commitment, it
2961-
// means this input asset isn't ours. We cannot
2962-
// find out if there were any purged assets in
2963-
// the commitment, so we just rely on all assets
2964-
// being present. If some purged assets are
2965-
// missing, then the anchor input equality check
2966-
// further down will fail.
2967-
rpcsLog.Warnf("Could not fetch input "+
2968-
"commitment for outpoint %v: %v",
2969-
outpoint, err)
2970-
2971-
continue
2972-
}
2973-
2974-
assetsToPurge := tapsend.ExtractUnSpendable(
2975-
input.Commitment,
2976-
)
2977-
for _, a := range assetsToPurge {
2978-
key := a.AssetCommitmentKey()
2979-
if purgedAssetsDeDup[outpoint] == nil {
2980-
purgedAssetsDeDup[outpoint] = make(
2981-
map[[32]byte]*asset.Asset,
2982-
)
2983-
}
2984-
2985-
purgedAssetsDeDup[outpoint][key] = a
2986-
}
2987-
}
2988-
}
2989-
2990-
// With the assets de-duplicated by their asset commitment key, we can
2991-
// now collect them grouped by input outpoint.
2992-
purgedAssets := make(map[wire.OutPoint][]*asset.Asset)
2993-
for outpoint, assets := range purgedAssetsDeDup {
2994-
for key := range assets {
2995-
purgedAssets[outpoint] = append(
2996-
purgedAssets[outpoint], assets[key],
2997-
)
2998-
}
2999-
}
3000-
30013010
// At this point all the virtual packet inputs and outputs should fully
30023011
// match the BTC level anchor transaction. Version 0 assets should also
30033012
// be signed now.
@@ -3072,7 +3081,8 @@ func (r *rpcServer) PublishAndLogTransfer(ctx context.Context,
30723081
// sure everything is in order. We start by validating the inputs.
30733082
allPackets := append([]*tappsbt.VPacket{}, activePackets...)
30743083
allPackets = append(allPackets, passivePackets...)
3075-
err = r.validateInputAssets(ctx, pkt, allPackets)
3084+
purgedAssets := r.collectPurgedAssets(ctx, allPackets)
3085+
err = r.validateInputAssets(ctx, pkt, allPackets, purgedAssets)
30763086
if err != nil {
30773087
return nil, fmt.Errorf("error validating input assets: %w", err)
30783088
}

0 commit comments

Comments
 (0)