Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
4fc779b
supplycommit: simplify file name from multi_sm_manager.go to manager.go
ffranr Aug 7, 2025
a668d28
supplycommit: simplify struct names for clarity
ffranr Aug 7, 2025
55a0810
supplycommit: add StartSupplyPublishFlow method to Manager
ffranr Aug 11, 2025
c4bcf0b
supplycommit: add AssetLookup interface to SupplyCommitManager
ffranr Aug 11, 2025
a786c59
supplycommit: check asset metadata before starting state machine
ffranr Aug 11, 2025
25c4c47
supplyverifier: add SupplySyncer for syncing supply commit leaves
ffranr Aug 22, 2025
2e60bca
tapdb: add supply syncer push log table
ffranr Aug 6, 2025
97d2d0e
tapdb: add SQL queries for supply syncer push log
ffranr Aug 6, 2025
a200c2a
tapdb: add SupplySyncerStore
ffranr Aug 6, 2025
a673676
proof: rename txSpendsPrevOut for export
ffranr Aug 20, 2025
5dd1b64
supplycommit: rename applyTreeUpdates for export
ffranr Aug 22, 2025
4e2f32d
supplycommit: add UpdateRootSupplyTree for verifier use
ffranr Aug 22, 2025
b528cc4
tapdb: extract fetchRootSupplyTreeInternal from FetchRootSupplyTree
ffranr Aug 22, 2025
2f2fcca
tapdb: add FetchSupplyTrees to retrieve all supply trees atomically
ffranr Aug 22, 2025
d8bbc5e
supplyverifier: add placeholder supply verifier state machine manager
ffranr Aug 22, 2025
76c7449
taprootassets: add supply verifier manager to main server config
ffranr Aug 8, 2025
aa57d6e
universerpc: add InsertSupplyCommit RPC endpoint
ffranr Sep 3, 2025
7dfd228
taprpc: remove FetchSupplyLeaves from public uni whitelist
ffranr Aug 12, 2025
8645530
multi: move inclusion proof feature to FetchSupplyLeaves RPC
ffranr Aug 12, 2025
6993f4c
rpcserver: add helper function unmarshalGroupKey
ffranr Aug 20, 2025
6e983e6
rpcserver: add marshalSupplyLeaves and unmarshalSupplyLeaves
ffranr Sep 3, 2025
17ea581
supplycommit: push supply commit to remote uni in CommitFinalizeState
ffranr Sep 3, 2025
cb1d7b6
tapdb+universe: consolidate code, link commitment to previous one
ffranr Aug 22, 2025
2fda505
rpcserver: set previously added BlockHeader and MerkleProof fields
ffranr Aug 21, 2025
bd0b3b4
tapdb+universe: add SpentCommitment to RootCommitment
guggero Aug 15, 2025
ac04f32
rpc: add field spent_commitment_outpoint to InsertSupplyCommitRequest
ffranr Aug 21, 2025
06c4679
taprootassets: add RpcSupplySync to bridge RPC and verifier syncer
ffranr Aug 25, 2025
f8086d4
tapcfg: pass the supply syncer into the supply commit manager
ffranr Sep 3, 2025
f38f51c
supplycommit: improve robustness of ApplyTreeUpdates
ffranr Aug 26, 2025
3b002ca
supplyverifier: add verification logic and use in uni server insert
ffranr Aug 23, 2025
2927455
supplyverifier+tapdb: add supply commit insert functionality
ffranr Aug 23, 2025
00d8bc5
mssmt: add CopyFilter to Tree interface and tree implementations
ffranr Aug 25, 2025
ce9135e
supplycommit+tapdb: extend FetchSubTrees with block height end param
ffranr Aug 25, 2025
a2c5a17
supplyverifier: add FetchCommitment method
ffranr Aug 25, 2025
ffe5775
supplycommit: add CalcTotalOutstandingSupply helper function
ffranr Sep 4, 2025
4ab7ebe
universerpc: add locator and update response in FetchSupplyCommit RPC
ffranr Aug 25, 2025
408338d
supplycommit: remove FetchCommitment from manager
ffranr Aug 25, 2025
52627bf
itest: extend testSupplyCommitIgnoreAsset to fetch from universe server
ffranr Aug 26, 2025
32f18c8
docs: add release notes
ffranr Aug 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 35 additions & 35 deletions cmd/commands/universe.go
Original file line number Diff line number Diff line change
Expand Up @@ -1638,21 +1638,6 @@ var fetchSupplyCommitCmd = cli.Command{
Usage: "the group key of the asset group to fetch",
Required: true,
},
&cli.StringSliceFlag{
Name: "issuance_leaf_keys",
Usage: "a list of issuance leaf keys to fetch " +
"inclusion proofs for",
},
&cli.StringSliceFlag{
Name: "burn_leaf_keys",
Usage: "a list of burn leaf keys to fetch inclusion " +
"proofs for",
},
&cli.StringSliceFlag{
Name: "ignore_leaf_keys",
Usage: "a list of ignore leaf keys to fetch " +
"inclusion proofs for",
},
},
Action: fetchSupplyCommit,
}
Expand All @@ -1668,26 +1653,6 @@ func fetchSupplyCommit(ctx *cli.Context) error {
},
}

issuanceKeys, err := parseHexStrings(
ctx.StringSlice("issuance_leaf_keys"),
)
if err != nil {
return fmt.Errorf("invalid issuance_leaf_keys: %w", err)
}
req.IssuanceLeafKeys = issuanceKeys

burnKeys, err := parseHexStrings(ctx.StringSlice("burn_leaf_keys"))
if err != nil {
return fmt.Errorf("invalid burn_leaf_keys: %w", err)
}
req.BurnLeafKeys = burnKeys

ignoreKeys, err := parseHexStrings(ctx.StringSlice("ignore_leaf_keys"))
if err != nil {
return fmt.Errorf("invalid ignore_leaf_keys: %w", err)
}
req.IgnoreLeafKeys = ignoreKeys

resp, err := client.FetchSupplyCommit(cliCtx, req)
if err != nil {
return err
Expand Down Expand Up @@ -1719,6 +1684,21 @@ var fetchSupplyLeavesCmd = cli.Command{
Usage: "the end of the block height range",
Required: true,
},
&cli.StringSliceFlag{
Name: "issuance_leaf_keys",
Usage: "a list of issuance leaf keys to fetch " +
"inclusion proofs for",
},
&cli.StringSliceFlag{
Name: "burn_leaf_keys",
Usage: "a list of burn leaf keys to fetch inclusion " +
"proofs for",
},
&cli.StringSliceFlag{
Name: "ignore_leaf_keys",
Usage: "a list of ignore leaf keys to fetch " +
"inclusion proofs for",
},
},
Action: fetchSupplyLeaves,
}
Expand All @@ -1736,6 +1716,26 @@ func fetchSupplyLeaves(ctx *cli.Context) error {
BlockHeightEnd: uint32(ctx.Uint64("block_height_end")),
}

issuanceKeys, err := parseHexStrings(
ctx.StringSlice("issuance_leaf_keys"),
)
if err != nil {
return fmt.Errorf("invalid issuance_leaf_keys: %w", err)
}
req.IssuanceLeafKeys = issuanceKeys

burnKeys, err := parseHexStrings(ctx.StringSlice("burn_leaf_keys"))
if err != nil {
return fmt.Errorf("invalid burn_leaf_keys: %w", err)
}
req.BurnLeafKeys = burnKeys

ignoreKeys, err := parseHexStrings(ctx.StringSlice("ignore_leaf_keys"))
if err != nil {
return fmt.Errorf("invalid ignore_leaf_keys: %w", err)
}
req.IgnoreLeafKeys = ignoreKeys

resp, err := client.FetchSupplyLeaves(cliCtx, req)
if err != nil {
return err
Expand Down
8 changes: 7 additions & 1 deletion config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/lightninglabs/taproot-assets/tapgarden"
"github.com/lightninglabs/taproot-assets/universe"
"github.com/lightninglabs/taproot-assets/universe/supplycommit"
"github.com/lightninglabs/taproot-assets/universe/supplyverifier"
"github.com/lightningnetwork/lnd"
"github.com/lightningnetwork/lnd/build"
"github.com/lightningnetwork/lnd/signal"
Expand Down Expand Up @@ -195,10 +196,15 @@ type Config struct {
// SupplyCommitManager is a service that is used to manage supply
// commitments for assets. Supply commitments are issuer published
// attestations of the total supply of an asset.
SupplyCommitManager *supplycommit.MultiStateMachineManager
SupplyCommitManager *supplycommit.Manager

IgnoreChecker *tapdb.CachingIgnoreChecker

// SupplyVerifyManager is a service that is used to verify supply
// commitments for assets. Supply commitments are issuer published
// attestations of the total supply of an asset.
SupplyVerifyManager *supplyverifier.Manager

UniverseArchive *universe.Archive

UniverseSyncer universe.Syncer
Expand Down
1 change: 1 addition & 0 deletions docs/release-notes/release-notes-0.7.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
- https://github.com/lightninglabs/taproot-assets/pull/1587
- https://github.com/lightninglabs/taproot-assets/pull/1716
- https://github.com/lightninglabs/taproot-assets/pull/1675
- https://github.com/lightninglabs/taproot-assets/pull/1674

- A new [address version 2 was introduced that supports grouped assets and
custom (sender-defined)
Expand Down
23 changes: 23 additions & 0 deletions fn/func.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,29 @@ func MapErr[I, O any, S []I](s S, f func(I) (O, error)) ([]O, error) {
return output, nil
}

// MapErrWithPtr applies the given fallible mapping function to each element of
// the given slice and generates a new slice. This is identical to MapErr, but
// can be used when the callback returns a pointer, and returns early if any
// single mapping fails.
func MapErrWithPtr[I, O any, S []I](s S, f func(I) (*O, error)) ([]O, error) {
output := make([]O, len(s))
for i, x := range s {
outPtr, err := f(x)
if err != nil {
return nil, err
}

if outPtr == nil {
return nil, fmt.Errorf("nil pointer returned for "+
"item %d", i)
}

output[i] = *outPtr
}

return output, nil
}

// FlatMapErr applies the given mapping function to each element of the given
// slice, concatenates the results into a new slice, and returns an error if
// the mapping function fails.
Expand Down
47 changes: 40 additions & 7 deletions itest/assertions.go
Original file line number Diff line number Diff line change
Expand Up @@ -2786,8 +2786,9 @@ func UpdateAndMineSupplyCommit(t *testing.T, ctx context.Context,
// it when the specified condition is met.
func WaitForSupplyCommit(t *testing.T, ctx context.Context,
tapd unirpc.UniverseClient, groupKeyBytes []byte,
spentCommitOutpoint fn.Option[wire.OutPoint],
condition func(*unirpc.FetchSupplyCommitResponse) bool,
) *unirpc.FetchSupplyCommitResponse {
) (*unirpc.FetchSupplyCommitResponse, wire.OutPoint) {

groupKeyReq := &unirpc.FetchSupplyCommitRequest_GroupKeyBytes{
GroupKeyBytes: groupKeyBytes,
Expand All @@ -2796,18 +2797,50 @@ func WaitForSupplyCommit(t *testing.T, ctx context.Context,
var fetchResp *unirpc.FetchSupplyCommitResponse
var err error

require.Eventually(t, func() bool {
fetchResp, err = tapd.FetchSupplyCommit(
ctx, &unirpc.FetchSupplyCommitRequest{
GroupKey: groupKeyReq,
// By default, we start the fetch from the very first commitment.
// If a spent outpoint is given, we start from there.
req := &unirpc.FetchSupplyCommitRequest{
GroupKey: groupKeyReq,
Locator: &unirpc.FetchSupplyCommitRequest_VeryFirst{
VeryFirst: true,
},
}

// nolint: lll
spentCommitOutpoint.WhenSome(func(outPoint wire.OutPoint) {
req = &unirpc.FetchSupplyCommitRequest{
GroupKey: groupKeyReq,
Locator: &unirpc.FetchSupplyCommitRequest_SpentCommitOutpoint{
SpentCommitOutpoint: &taprpc.OutPoint{
Txid: outPoint.Hash[:],
OutputIndex: outPoint.Index,
},
},
)
}
})

require.Eventually(t, func() bool {
fetchResp, err = tapd.FetchSupplyCommit(ctx, req)
if err != nil {
return false
}

return fetchResp != nil && condition(fetchResp)
}, defaultWaitTimeout, time.Second)

return fetchResp
// Return the supply commit outpoint used to fetch the next supply
// commitment. The next commitment is retrieved by referencing the
// outpoint of the previously spent commitment.
require.NotNil(t, fetchResp)

var msgTx wire.MsgTx
err = msgTx.Deserialize(bytes.NewReader(fetchResp.ChainData.Txn))
require.NoError(t, err)

supplyCommitOutpoint := wire.OutPoint{
Hash: msgTx.TxHash(),
Index: fetchResp.ChainData.TxOutIdx,
}

return fetchResp, supplyCommitOutpoint
}
31 changes: 16 additions & 15 deletions itest/supply_commit_mint_burn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
taprootassets "github.com/lightninglabs/taproot-assets"
"github.com/lightninglabs/taproot-assets/fn"
"github.com/lightninglabs/taproot-assets/taprpc"
Expand Down Expand Up @@ -48,18 +49,19 @@ func testSupplyCommitMintBurn(t *harnessTest) {
// Update the on-chain supply commitment for the asset group.
//
// TODO(roasbeef): still rely on the time based ticker here?
t.Log("Updating and mining supply commitment for asset group")
t.Log("Create first supply commitment tx for asset group")
UpdateAndMineSupplyCommit(
t.t, ctxb, t.tapd, t.lndHarness.Miner().Client,
groupKeyBytes, 1,
)

// Fetch the latest supply commitment for the asset group.
t.Log("Fetching supply commitment to verify mint leaves")
fetchResp := WaitForSupplyCommit(
t.t, ctxb, t.tapd, groupKeyBytes,
t.Log("Fetching first supply commitment to verify mint leaves")
fetchResp, supplyOutpoint := WaitForSupplyCommit(
t.t, ctxb, t.tapd, groupKeyBytes, fn.None[wire.OutPoint](),
func(resp *unirpc.FetchSupplyCommitResponse) bool {
return resp.BlockHeight > 0 && len(resp.BlockHash) > 0
return resp.ChainData.BlockHeight > 0 &&
len(resp.ChainData.BlockHash) > 0
},
)

Expand All @@ -72,7 +74,7 @@ func testSupplyCommitMintBurn(t *harnessTest) {

// Verify the issuance leaf inclusion in the supply tree.
AssertSubtreeInclusionProof(
t, fetchResp.SupplyCommitmentRoot.RootHash,
t, fetchResp.ChainData.SupplyRootHash,
fetchResp.IssuanceSubtreeRoot,
)

Expand Down Expand Up @@ -106,8 +108,6 @@ func testSupplyCommitMintBurn(t *harnessTest) {
)

t.Log("Updating supply commitment after second mint")

// Update and mine the supply commitment after second mint.
UpdateAndMineSupplyCommit(
t.t, ctxb, t.tapd, t.lndHarness.Miner().Client,
groupKeyBytes, 1,
Expand All @@ -119,8 +119,8 @@ func testSupplyCommitMintBurn(t *harnessTest) {
expectedTotal := int64(
mintReq.Asset.Amount + secondMintReq.Asset.Amount,
)
fetchResp = WaitForSupplyCommit(
t.t, ctxb, t.tapd, groupKeyBytes,
fetchResp, supplyOutpoint = WaitForSupplyCommit(
t.t, ctxb, t.tapd, groupKeyBytes, fn.Some(supplyOutpoint),
func(resp *unirpc.FetchSupplyCommitResponse) bool {
return resp.IssuanceSubtreeRoot != nil &&
resp.IssuanceSubtreeRoot.RootNode.RootSum == expectedTotal //nolint:lll
Expand Down Expand Up @@ -175,7 +175,8 @@ func testSupplyCommitMintBurn(t *harnessTest) {
t.Log("Verifying supply tree includes burn leaves")

// Fetch and verify the supply tree now includes burn leaves.
fetchResp = WaitForSupplyCommit(t.t, ctxb, t.tapd, groupKeyBytes,
fetchResp, _ = WaitForSupplyCommit(
t.t, ctxb, t.tapd, groupKeyBytes, fn.Some(supplyOutpoint),
func(resp *unirpc.FetchSupplyCommitResponse) bool {
return resp.BurnSubtreeRoot != nil &&
resp.BurnSubtreeRoot.RootNode.RootSum == int64(burnAmt) //nolint:lll
Expand All @@ -184,7 +185,7 @@ func testSupplyCommitMintBurn(t *harnessTest) {

// Verify the burn subtree inclusion in the supply tree.
AssertSubtreeInclusionProof(
t, fetchResp.SupplyCommitmentRoot.RootHash,
t, fetchResp.ChainData.SupplyRootHash,
fetchResp.BurnSubtreeRoot,
)

Expand Down Expand Up @@ -234,16 +235,16 @@ func testSupplyCommitMintBurn(t *harnessTest) {
block := finalMinedBlocks[0]
blockHash, _ := t.lndHarness.Miner().GetBestBlock()

fetchBlockHash, err := chainhash.NewHash(fetchResp.BlockHash)
fetchBlockHash, err := chainhash.NewHash(fetchResp.ChainData.BlockHash)
require.NoError(t.t, err)
require.True(t.t, fetchBlockHash.IsEqual(blockHash))

// Re-compute the supply commitment root hash from the latest fetch,
// then use that to derive the expected commitment output.
supplyCommitRootHash := fn.ToArray[[32]byte](
fetchResp.SupplyCommitmentRoot.RootHash,
fetchResp.ChainData.SupplyRootHash,
)
internalKey, err := btcec.ParsePubKey(fetchResp.AnchorTxOutInternalKey)
internalKey, err := btcec.ParsePubKey(fetchResp.ChainData.InternalKey)
require.NoError(t.t, err)
expectedTxOut, _, err := supplycommit.RootCommitTxOut(
internalKey, nil, supplyCommitRootHash,
Expand Down
Loading