@@ -1148,6 +1148,17 @@ func (b *BatchCaretaker) stateStep(currentState BatchState) (BatchState, error)
1148
1148
return 0 , fmt .Errorf ("unable to confirm batch: %w" , err )
1149
1149
}
1150
1150
1151
+ // Send supply commitment events for all minted assets before
1152
+ // finalizing the batch. This ensures that supply commitments
1153
+ // are tracked before the batch is considered complete.
1154
+ err = b .sendSupplyCommitEvents (
1155
+ ctx , anchorAssets , nonAnchorAssets , mintingProofs ,
1156
+ )
1157
+ if err != nil {
1158
+ return 0 , fmt .Errorf ("unable to send supply commit " +
1159
+ "events: %w" , err )
1160
+ }
1161
+
1151
1162
// Now that we've confirmed the batch, we'll hand over the
1152
1163
// proofs to the re-org watcher.
1153
1164
if err := b .cfg .ProofWatcher .WatchProofs (
@@ -1432,6 +1443,116 @@ func GenHeaderVerifier(ctx context.Context,
1432
1443
}
1433
1444
}
1434
1445
1446
+ // sendSupplyCommitEvents sends supply commitment events for all minted assets
1447
+ // in the batch to track them in the supply commitment state machine.
1448
+ func (b * BatchCaretaker ) sendSupplyCommitEvents (ctx context.Context ,
1449
+ anchorAssets , nonAnchorAssets []* asset.Asset ,
1450
+ mintingProofs proof.AssetProofs ) error {
1451
+
1452
+ // If no supply commit manager is configured, skip this step.
1453
+ if b .cfg .MintSupplyCommitter == nil {
1454
+ return nil
1455
+ }
1456
+
1457
+ // If no delegation key checker is configured, skip this step. As if we
1458
+ // need this to figure out if we made the asset or not.
1459
+ if b .cfg .DelegationKeyChecker == nil {
1460
+ return nil
1461
+ }
1462
+
1463
+ // We'll combine the anchor and non-anchor assets into a single slice
1464
+ // that we'll run through below.
1465
+ allAssets := append (anchorAssets , nonAnchorAssets ... )
1466
+
1467
+ delChecker := b .cfg .DelegationKeyChecker
1468
+
1469
+ // We filter the assets to only include those that have a delegation
1470
+ // key. As only those have a supply commitment maintained.
1471
+ assetsWithDelegation := fn .Filter (allAssets , func (a * asset.Asset ) bool {
1472
+ hasDelegationKey , err := delChecker .HasDelegationKey (
1473
+ ctx , a .ID (),
1474
+ )
1475
+ if err != nil {
1476
+ log .Debugf ("Error checking delegation key for " +
1477
+ "asset %x: %v" , a .ID (), err )
1478
+ return false
1479
+ }
1480
+ if ! hasDelegationKey {
1481
+ log .Debugf ("Skipping supply commit event for " +
1482
+ "asset %x: delegation key not controlled " +
1483
+ "locally" ,
1484
+ a .ID ())
1485
+ }
1486
+ return hasDelegationKey
1487
+ })
1488
+
1489
+ // For each of the assets that we just created with a delegation key,
1490
+ // we'll create then send a supply commit event so the committer can
1491
+ // take care of it.
1492
+ for _ , mintedAsset := range assetsWithDelegation {
1493
+ // First, we'll extract the minting proof based on the srcipt
1494
+ // key, and extract the very last proof from that.
1495
+ scriptKey := asset .ToSerialized (mintedAsset .ScriptKey .PubKey )
1496
+ mintingProof , ok := mintingProofs [scriptKey ]
1497
+ if ! ok {
1498
+ return fmt .Errorf ("missing minting proof for asset " +
1499
+ "with script key %x" , scriptKey [:])
1500
+ }
1501
+
1502
+ proofBlob , err := proof .EncodeAsProofFile (mintingProof )
1503
+ if err != nil {
1504
+ return fmt .Errorf ("unable to encode proof as " +
1505
+ "file: %w" , err )
1506
+ }
1507
+ proofFile , err := proof .DecodeFile (proofBlob )
1508
+ if err != nil {
1509
+ return fmt .Errorf ("unable to decode proof " +
1510
+ "file: %w" , err )
1511
+ }
1512
+ leafProof , err := proofFile .LastProof ()
1513
+ if err != nil {
1514
+ return fmt .Errorf ("unable to get leaf proof: %w" , err )
1515
+ }
1516
+
1517
+ // With the proof extracted, we can now create the universe
1518
+ // key and leaf.
1519
+ universeKey := universe.BaseLeafKey {
1520
+ OutPoint : mintedAsset .Genesis .FirstPrevOut ,
1521
+ ScriptKey : & mintedAsset .ScriptKey ,
1522
+ }
1523
+ uniqueLeafKey := universe.AssetLeafKey {
1524
+ BaseLeafKey : universeKey ,
1525
+ AssetID : mintedAsset .ID (),
1526
+ }
1527
+ universeLeaf := universe.Leaf {
1528
+ GenesisWithGroup : universe.GenesisWithGroup {
1529
+ Genesis : mintedAsset .Genesis ,
1530
+ GroupKey : mintedAsset .GroupKey ,
1531
+ },
1532
+ RawProof : proofBlob ,
1533
+ Asset : & leafProof .Asset ,
1534
+ Amt : mintedAsset .Amount ,
1535
+ }
1536
+ assetSpec := asset .NewSpecifierOptionalGroupKey (
1537
+ mintedAsset .ID (), mintedAsset .GroupKey ,
1538
+ )
1539
+
1540
+ // Finally we send all of the above to the supply commiter.
1541
+ err = b .cfg .MintSupplyCommitter .SendMintEvent (
1542
+ ctx , assetSpec , uniqueLeafKey , universeLeaf ,
1543
+ )
1544
+ if err != nil {
1545
+ return fmt .Errorf ("unable to send mint event for " +
1546
+ "asset %x: %w" , mintedAsset .ID (), err )
1547
+ }
1548
+
1549
+ log .Debugf ("Sent supply commit mint event for asset %x" ,
1550
+ mintedAsset .ID ())
1551
+ }
1552
+
1553
+ return nil
1554
+ }
1555
+
1435
1556
// assetGroupCacheSize is the size of the cache for group keys.
1436
1557
const assetGroupCacheSize = 10000
1437
1558
0 commit comments