@@ -4594,6 +4594,213 @@ func (r *rpcServer) FetchSupplyLeaves(ctx context.Context,
4594
4594
}, nil
4595
4595
}
4596
4596
4597
+ // unmarshalSupplyCommitChainData converts an RPC SupplyCommitChainData into
4598
+ // both a supplycommit.RootCommitment and supplycommit.ChainProof.
4599
+ func unmarshalSupplyCommitChainData (
4600
+ rpcData * unirpc.SupplyCommitChainData ) (* supplycommit.RootCommitment ,
4601
+ * supplycommit.ChainProof , error ) {
4602
+
4603
+ if rpcData == nil {
4604
+ return nil , nil , fmt .Errorf ("supply commit chain data is nil" )
4605
+ }
4606
+
4607
+ var txn wire.MsgTx
4608
+ err := txn .Deserialize (bytes .NewReader (rpcData .Txn ))
4609
+ if err != nil {
4610
+ return nil , nil , fmt .Errorf ("unable to deserialize " +
4611
+ "transaction: %w" , err )
4612
+ }
4613
+
4614
+ internalKey , err := btcec .ParsePubKey (rpcData .InternalKey )
4615
+ if err != nil {
4616
+ return nil , nil , fmt .Errorf ("unable to parse internal key: %w" ,
4617
+ err )
4618
+ }
4619
+
4620
+ outputKey , err := btcec .ParsePubKey (rpcData .OutputKey )
4621
+ if err != nil {
4622
+ return nil , nil , fmt .Errorf ("unable to parse output key: %w" ,
4623
+ err )
4624
+ }
4625
+
4626
+ // Convert supply root hash.
4627
+ if len (rpcData .SupplyRootHash ) != 32 {
4628
+ return nil , nil , fmt .Errorf ("invalid supply root hash size: " +
4629
+ "expected %d, got %d" , 32 , len (rpcData .SupplyRootHash ))
4630
+ }
4631
+ var supplyRootHash mssmt.NodeHash
4632
+ copy (supplyRootHash [:], rpcData .SupplyRootHash )
4633
+
4634
+ // Create commitment block from the hash.
4635
+ var commitmentBlock fn.Option [supplycommit.CommitmentBlock ]
4636
+ if len (rpcData .BlockHash ) > 0 {
4637
+ if len (rpcData .BlockHash ) != chainhash .HashSize {
4638
+ return nil , nil , fmt .Errorf ("invalid block hash size: " +
4639
+ "expected %d, got %d" , chainhash .HashSize ,
4640
+ len (rpcData .BlockHash ))
4641
+ }
4642
+ var blockHash chainhash.Hash
4643
+ copy (blockHash [:], rpcData .BlockHash )
4644
+
4645
+ commitmentBlock = fn .Some (supplycommit.CommitmentBlock {
4646
+ Height : rpcData .BlockHeight ,
4647
+ Hash : blockHash ,
4648
+ TxIndex : rpcData .TxIndex ,
4649
+ })
4650
+ }
4651
+
4652
+ rootCommitment := & supplycommit.RootCommitment {
4653
+ Txn : & txn ,
4654
+ TxOutIdx : rpcData .TxOutIdx ,
4655
+ InternalKey : keychain.KeyDescriptor {
4656
+ PubKey : internalKey ,
4657
+ },
4658
+ OutputKey : outputKey ,
4659
+ SupplyRoot : mssmt .NewComputedBranch (
4660
+ supplyRootHash , rpcData .SupplyRootSum ,
4661
+ ),
4662
+ CommitmentBlock : commitmentBlock ,
4663
+ }
4664
+
4665
+ var blockHeader wire.BlockHeader
4666
+ err = blockHeader .Deserialize (bytes .NewReader (rpcData .BlockHeader ))
4667
+ if err != nil {
4668
+ return nil , nil , fmt .Errorf ("unable to deserialize block " +
4669
+ "header: %w" , err )
4670
+ }
4671
+
4672
+ var merkleProof proof.TxMerkleProof
4673
+ err = merkleProof .Decode (bytes .NewReader (rpcData .TxBlockMerkleProof ))
4674
+ if err != nil {
4675
+ return nil , nil , fmt .Errorf ("unable to decode merkle proof: %w" ,
4676
+ err )
4677
+ }
4678
+
4679
+ chainProof := & supplycommit.ChainProof {
4680
+ Header : blockHeader ,
4681
+ BlockHeight : rpcData .BlockHeight ,
4682
+ MerkleProof : merkleProof ,
4683
+ TxIndex : rpcData .TxIndex ,
4684
+ }
4685
+
4686
+ return rootCommitment , chainProof , nil
4687
+ }
4688
+
4689
+ // InsertSupplyCommit stores a verified supply commitment for the given
4690
+ // asset group in the node's local database.
4691
+ func (r * rpcServer ) InsertSupplyCommit (ctx context.Context ,
4692
+ req * unirpc.InsertSupplyCommitRequest ) (
4693
+ * unirpc.InsertSupplyCommitResponse , error ) {
4694
+
4695
+ // Parse asset group key from the request.
4696
+ var groupPubKey btcec.PublicKey
4697
+
4698
+ switch {
4699
+ case len (req .GetGroupKeyBytes ()) > 0 :
4700
+ gk , err := btcec .ParsePubKey (req .GetGroupKeyBytes ())
4701
+ if err != nil {
4702
+ return nil , fmt .Errorf ("parsing group key: %w" , err )
4703
+ }
4704
+
4705
+ groupPubKey = * gk
4706
+
4707
+ case len (req .GetGroupKeyStr ()) > 0 :
4708
+ groupKeyBytes , err := hex .DecodeString (req .GetGroupKeyStr ())
4709
+ if err != nil {
4710
+ return nil , fmt .Errorf ("decoding group key: %w" , err )
4711
+ }
4712
+
4713
+ gk , err := btcec .ParsePubKey (groupKeyBytes )
4714
+ if err != nil {
4715
+ return nil , fmt .Errorf ("parsing group key: %w" , err )
4716
+ }
4717
+
4718
+ groupPubKey = * gk
4719
+
4720
+ default :
4721
+ return nil , fmt .Errorf ("group key unspecified" )
4722
+ }
4723
+
4724
+ // Log the operation for debugging purposes.
4725
+ rpcsLog .Debugf ("InsertSupplyCommitment called for group key: %x" ,
4726
+ groupPubKey .SerializeCompressed ())
4727
+
4728
+ // Unmarshal the supply commit chain data.
4729
+ rootCommitment , chainProof , err := unmarshalSupplyCommitChainData (
4730
+ req .ChainData ,
4731
+ )
4732
+ if err != nil {
4733
+ return nil , fmt .Errorf ("failed to unmarshal chain data: %w" ,
4734
+ err )
4735
+ }
4736
+
4737
+ // Initialize the SupplyLeaves structure to collect all unmarshalled
4738
+ // events.
4739
+ var supplyLeaves supplycommit.SupplyLeaves
4740
+
4741
+ // Process issuance leaves.
4742
+ supplyLeaves .IssuanceLeafEntries = make (
4743
+ []supplycommit.NewMintEvent , 0 , len (req .IssuanceLeaves ),
4744
+ )
4745
+ for _ , rpcLeaf := range req .IssuanceLeaves {
4746
+ mintEvent , err := unmarshalMintSupplyLeaf (rpcLeaf )
4747
+ if err != nil {
4748
+ return nil , fmt .Errorf ("failed to unmarshal issuance " +
4749
+ "leaf: %w" , err )
4750
+ }
4751
+ supplyLeaves .IssuanceLeafEntries = append (
4752
+ supplyLeaves .IssuanceLeafEntries , * mintEvent ,
4753
+ )
4754
+ }
4755
+
4756
+ // Process burn leaves.
4757
+ supplyLeaves .BurnLeafEntries = make (
4758
+ []supplycommit.NewBurnEvent , 0 , len (req .BurnLeaves ),
4759
+ )
4760
+ for _ , rpcLeaf := range req .BurnLeaves {
4761
+ burnEvent , err := unmarshalBurnSupplyLeaf (rpcLeaf )
4762
+ if err != nil {
4763
+ return nil , fmt .Errorf ("failed to unmarshal burn " +
4764
+ "leaf: %w" , err )
4765
+ }
4766
+ supplyLeaves .BurnLeafEntries = append (
4767
+ supplyLeaves .BurnLeafEntries , * burnEvent ,
4768
+ )
4769
+ }
4770
+
4771
+ // Process ignore leaves.
4772
+ supplyLeaves .IgnoreLeafEntries = make (
4773
+ []supplycommit.NewIgnoreEvent , 0 , len (req .IgnoreLeaves ),
4774
+ )
4775
+ for _ , rpcLeaf := range req .IgnoreLeaves {
4776
+ ignoreEvent , err := unmarshalIgnoreSupplyLeaf (rpcLeaf )
4777
+ if err != nil {
4778
+ return nil , fmt .Errorf ("failed to unmarshal ignore " +
4779
+ "leaf: %w" , err )
4780
+ }
4781
+ supplyLeaves .IgnoreLeafEntries = append (
4782
+ supplyLeaves .IgnoreLeafEntries , * ignoreEvent ,
4783
+ )
4784
+ }
4785
+
4786
+ rpcsLog .Debugf ("Successfully unmarshalled commitment, %d issuance, " +
4787
+ "%d burn, and %d ignore leaves, and chain proof" ,
4788
+ len (supplyLeaves .IssuanceLeafEntries ),
4789
+ len (supplyLeaves .BurnLeafEntries ),
4790
+ len (supplyLeaves .IgnoreLeafEntries ))
4791
+
4792
+ assetSpec := asset .NewSpecifierFromGroupKey (groupPubKey )
4793
+ err = r .cfg .SupplyVerifyManager .InsertSupplyCommit (
4794
+ ctx , assetSpec , * rootCommitment , supplyLeaves , * chainProof ,
4795
+ )
4796
+ if err != nil {
4797
+ return nil , fmt .Errorf ("failed to insert supply commitment: %w" ,
4798
+ err )
4799
+ }
4800
+
4801
+ return & unirpc.InsertSupplyCommitResponse {}, nil
4802
+ }
4803
+
4597
4804
// SubscribeSendAssetEventNtfns registers a subscription to the event
4598
4805
// notification stream which relates to the asset sending process.
4599
4806
func (r * rpcServer ) SubscribeSendAssetEventNtfns (
0 commit comments