Skip to content

Commit 6d58b38

Browse files
committed
multi: refactor chain asset creation for better re-use
We'll be using this refactored functionality in the next commits.
1 parent 3fbacbb commit 6d58b38

File tree

3 files changed

+101
-71
lines changed

3 files changed

+101
-71
lines changed

proof/proof.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/btcsuite/btcd/blockchain"
1010
"github.com/btcsuite/btcd/wire"
1111
"github.com/lightninglabs/taproot-assets/asset"
12+
"github.com/lightninglabs/taproot-assets/commitment"
1213
"github.com/lightningnetwork/lnd/input"
1314
"github.com/lightningnetwork/lnd/tlv"
1415
)
@@ -489,6 +490,43 @@ func (p *Proof) IsUnknownVersion() bool {
489490
}
490491
}
491492

493+
// ToChainAsset converts the proof to a ChainAsset.
494+
func (p *Proof) ToChainAsset() (asset.ChainAsset, error) {
495+
emptyAsset := asset.ChainAsset{}
496+
497+
if p.InclusionProof.CommitmentProof == nil {
498+
return emptyAsset, fmt.Errorf("inclusion proof is missing " +
499+
"commitment proof")
500+
}
501+
502+
commitmentProof := p.InclusionProof.CommitmentProof
503+
tsSibling, tsHash, err := commitment.MaybeEncodeTapscriptPreimage(
504+
commitmentProof.TapSiblingPreimage,
505+
)
506+
if err != nil {
507+
return emptyAsset, fmt.Errorf("error encoding tapscript "+
508+
"sibling: %w", err)
509+
}
510+
511+
tapProof, err := commitmentProof.DeriveByAssetInclusion(&p.Asset)
512+
if err != nil {
513+
return emptyAsset, fmt.Errorf("error deriving inclusion "+
514+
"proof: %w", err)
515+
}
516+
517+
merkleRoot := tapProof.TapscriptRoot(tsHash)
518+
return asset.ChainAsset{
519+
Asset: &p.Asset,
520+
AnchorTx: &p.AnchorTx,
521+
AnchorBlockHash: p.BlockHeader.BlockHash(),
522+
AnchorOutpoint: p.OutPoint(),
523+
AnchorBlockHeight: p.BlockHeight,
524+
AnchorInternalKey: p.InclusionProof.InternalKey,
525+
AnchorMerkleRoot: merkleRoot[:],
526+
AnchorTapscriptSibling: tsSibling,
527+
}, nil
528+
}
529+
492530
// Ensure Proof implements the tlv.RecordProducer interface.
493531
var _ tlv.RecordProducer = (*Proof)(nil)
494532

rpcserver.go

Lines changed: 22 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,8 +1091,12 @@ func (r *rpcServer) fetchRpcAssets(ctx context.Context, withWitness,
10911091

10921092
rpcAssets := make([]*taprpc.Asset, len(assets))
10931093
for i, a := range assets {
1094+
if a == nil {
1095+
return nil, fmt.Errorf("nil asset at index %d", i)
1096+
}
1097+
10941098
rpcAssets[i], err = r.MarshalChainAsset(
1095-
ctx, a, nil, withWitness, r.cfg.AddrBook,
1099+
ctx, *a, nil, withWitness, r.cfg.AddrBook,
10961100
)
10971101
if err != nil {
10981102
return nil, fmt.Errorf("unable to marshal asset: %w",
@@ -1104,7 +1108,7 @@ func (r *rpcServer) fetchRpcAssets(ctx context.Context, withWitness,
11041108
}
11051109

11061110
// MarshalChainAsset marshals the given chain asset into an RPC asset.
1107-
func (r *rpcServer) MarshalChainAsset(ctx context.Context, a *asset.ChainAsset,
1111+
func (r *rpcServer) MarshalChainAsset(ctx context.Context, a asset.ChainAsset,
11081112
meta *proof.MetaReveal, withWitness bool,
11091113
keyRing taprpc.KeyLookup) (*taprpc.Asset, error) {
11101114

@@ -1125,38 +1129,9 @@ func (r *rpcServer) MarshalChainAsset(ctx context.Context, a *asset.ChainAsset,
11251129
return nil, err
11261130
}
11271131

1128-
rpcAsset, err := taprpc.MarshalAsset(
1129-
ctx, a.Asset, a.IsSpent, withWitness, keyRing, decDisplay,
1132+
return taprpc.MarshalChainAsset(
1133+
ctx, a, decDisplay, withWitness, keyRing,
11301134
)
1131-
if err != nil {
1132-
return nil, err
1133-
}
1134-
1135-
var anchorTxBytes []byte
1136-
if a.AnchorTx != nil {
1137-
anchorTxBytes, err = serialize(a.AnchorTx)
1138-
if err != nil {
1139-
return nil, fmt.Errorf("unable to serialize anchor "+
1140-
"tx: %w", err)
1141-
}
1142-
}
1143-
1144-
rpcAsset.ChainAnchor = &taprpc.AnchorInfo{
1145-
AnchorTx: anchorTxBytes,
1146-
AnchorBlockHash: a.AnchorBlockHash.String(),
1147-
AnchorOutpoint: a.AnchorOutpoint.String(),
1148-
InternalKey: a.AnchorInternalKey.SerializeCompressed(),
1149-
MerkleRoot: a.AnchorMerkleRoot,
1150-
TapscriptSibling: a.AnchorTapscriptSibling,
1151-
BlockHeight: a.AnchorBlockHeight,
1152-
}
1153-
1154-
if a.AnchorLeaseOwner != [32]byte{} {
1155-
rpcAsset.LeaseOwner = a.AnchorLeaseOwner[:]
1156-
rpcAsset.LeaseExpiry = a.AnchorLeaseExpiry.UTC().Unix()
1157-
}
1158-
1159-
return rpcAsset, nil
11601135
}
11611136

11621137
func (r *rpcServer) listBalancesByAsset(ctx context.Context,
@@ -1750,10 +1725,6 @@ func (r *rpcServer) marshalProof(ctx context.Context, p *proof.Proof,
17501725
rpcMeta *taprpc.AssetMeta
17511726
rpcGenesis = p.GenesisReveal
17521727
rpcGroupKey = p.GroupKeyReveal
1753-
anchorOutpoint = wire.OutPoint{
1754-
Hash: p.AnchorTx.TxHash(),
1755-
Index: p.InclusionProof.OutputIndex,
1756-
}
17571728
txMerkleProof = p.TxMerkleProof
17581729
inclusionProof = p.InclusionProof
17591730
splitRootProof = p.SplitRootProof
@@ -1772,31 +1743,10 @@ func (r *rpcServer) marshalProof(ctx context.Context, p *proof.Proof,
17721743
err)
17731744
}
17741745

1775-
if inclusionProof.CommitmentProof == nil {
1776-
return nil, fmt.Errorf("inclusion proof is missing " +
1777-
"commitment proof")
1778-
}
1779-
tsSibling, tsHash, err := commitment.MaybeEncodeTapscriptPreimage(
1780-
inclusionProof.CommitmentProof.TapSiblingPreimage,
1781-
)
1782-
if err != nil {
1783-
return nil, fmt.Errorf("error encoding tapscript sibling: %w",
1784-
err)
1785-
}
1786-
1787-
tapProof, err := inclusionProof.CommitmentProof.DeriveByAssetInclusion(
1788-
&p.Asset,
1789-
)
1790-
if err != nil {
1791-
return nil, fmt.Errorf("error deriving inclusion proof: %w",
1792-
err)
1793-
}
1794-
merkleRoot := tapProof.TapscriptRoot(tsHash)
1795-
17961746
var exclusionProofs [][]byte
17971747
for _, exclusionProof := range p.ExclusionProofs {
17981748
var exclusionProofBuf bytes.Buffer
1799-
err = exclusionProof.Encode(&exclusionProofBuf)
1749+
err := exclusionProof.Encode(&exclusionProofBuf)
18001750
if err != nil {
18011751
return nil, fmt.Errorf("unable to encode exclusion "+
18021752
"proofs: %w", err)
@@ -1808,7 +1758,7 @@ func (r *rpcServer) marshalProof(ctx context.Context, p *proof.Proof,
18081758

18091759
var splitRootProofBuf bytes.Buffer
18101760
if splitRootProof != nil {
1811-
err = splitRootProof.Encode(&splitRootProofBuf)
1761+
err := splitRootProof.Encode(&splitRootProofBuf)
18121762
if err != nil {
18131763
return nil, fmt.Errorf("unable to encode split root "+
18141764
"proof: %w", err)
@@ -1828,18 +1778,19 @@ func (r *rpcServer) marshalProof(ctx context.Context, p *proof.Proof,
18281778
}
18291779
}
18301780

1831-
rpcAsset, err := r.MarshalChainAsset(ctx, &asset.ChainAsset{
1832-
Asset: &p.Asset,
1833-
AnchorTx: &p.AnchorTx,
1834-
AnchorBlockHash: p.BlockHeader.BlockHash(),
1835-
AnchorBlockHeight: p.BlockHeight,
1836-
AnchorOutpoint: anchorOutpoint,
1837-
AnchorInternalKey: p.InclusionProof.InternalKey,
1838-
AnchorMerkleRoot: merkleRoot[:],
1839-
AnchorTapscriptSibling: tsSibling,
1840-
}, p.MetaReveal, withPrevWitnesses, r.cfg.AddrBook)
1781+
chainAsset, err := p.ToChainAsset()
18411782
if err != nil {
1842-
return nil, err
1783+
return nil, fmt.Errorf("unable to convert proof to chain "+
1784+
"asset: %w", err)
1785+
}
1786+
1787+
rpcAsset, err := r.MarshalChainAsset(
1788+
ctx, chainAsset, p.MetaReveal, withPrevWitnesses,
1789+
r.cfg.AddrBook,
1790+
)
1791+
if err != nil {
1792+
return nil, fmt.Errorf("unable to marshal chain asset: %w",
1793+
err)
18431794
}
18441795

18451796
if withMetaReveal {

taprpc/marshal.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,47 @@ func UnmarshalGroupWitness(wit *GroupWitness) (*asset.PendingGroupWitness,
511511
}, nil
512512
}
513513

514+
// MarshalChainAsset marshals a chain asset into its RPC counterpart.
515+
func MarshalChainAsset(ctx context.Context, a asset.ChainAsset,
516+
decDisplay fn.Option[uint32], withWitness bool,
517+
keyRing KeyLookup) (*Asset, error) {
518+
519+
rpcAsset, err := MarshalAsset(
520+
ctx, a.Asset, a.IsSpent, withWitness, keyRing, decDisplay,
521+
)
522+
if err != nil {
523+
return nil, err
524+
}
525+
526+
var anchorTxBytes []byte
527+
if a.AnchorTx != nil {
528+
var b bytes.Buffer
529+
err := a.AnchorTx.Serialize(&b)
530+
if err != nil {
531+
return nil, fmt.Errorf("unable to serialize anchor "+
532+
"tx: %w", err)
533+
}
534+
anchorTxBytes = b.Bytes()
535+
}
536+
537+
rpcAsset.ChainAnchor = &AnchorInfo{
538+
AnchorTx: anchorTxBytes,
539+
AnchorBlockHash: a.AnchorBlockHash.String(),
540+
AnchorOutpoint: a.AnchorOutpoint.String(),
541+
InternalKey: a.AnchorInternalKey.SerializeCompressed(),
542+
MerkleRoot: a.AnchorMerkleRoot,
543+
TapscriptSibling: a.AnchorTapscriptSibling,
544+
BlockHeight: a.AnchorBlockHeight,
545+
}
546+
547+
if a.AnchorLeaseOwner != [32]byte{} {
548+
rpcAsset.LeaseOwner = a.AnchorLeaseOwner[:]
549+
rpcAsset.LeaseExpiry = a.AnchorLeaseExpiry.UTC().Unix()
550+
}
551+
552+
return rpcAsset, nil
553+
}
554+
514555
// MarshalAsset converts an asset to its rpc representation.
515556
func MarshalAsset(ctx context.Context, a *asset.Asset,
516557
isSpent, withWitness bool, keyRing KeyLookup,

0 commit comments

Comments
 (0)