Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions itest/mint_fund_seal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,9 @@ func testMintExternalGroupKeyChantools(t *harnessTest) {
mintReq2 := CopyRequest(issuableAssets[0])
mintReq2.Asset.Name = "itestbuxx-money-printer-brrr-tranche-2"
mintReq2.Asset.ExternalGroupKey = externalGroupKey
mintReq2.Asset.GroupedAsset = true
mintReq2.Asset.NewGroupedAsset = false
mintReq2.Asset.GroupKey = batchAssets[0].AssetGroup.TweakedGroupKey
Comment on lines +580 to +582
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is mintReq2.Asset.GroupedAsset = true necessary here? I would have expected setting mintReq2.Asset.ExternalGroupKey to imply group asset sufficiently.

Is setting these fields necessary or are we just covering all possibilities here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The RPC (and by extension the CLI) interface for the minting call is not optimal and quite confusing. See #1517 (comment)

So you need to set at least one of the GroupedAsset or NewGroupedAsset to true if you want to start or issue into a group, independent of the other fields.


assetReqs2 := []*mintrpc.MintAssetRequest{mintReq2}

Expand Down
2 changes: 1 addition & 1 deletion itest/multi_asset_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ func testMintMultiAssetGroupErrors(t *harnessTest) {

groupedAsset.Asset.GroupAnchor = validAnchorName
_, err = t.tapd.MintAsset(ctxb, groupedAsset)
require.ErrorContains(t.t, err, "has emission disabled")
require.ErrorContains(t.t, err, "isn't starting a new group")

// Finally, we'll modify the assets to make the multi-asset group valid.
validAnchor.Asset.NewGroupedAsset = true
Expand Down
4 changes: 3 additions & 1 deletion itest/re-issuance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,9 @@ func testMintWithGroupKeyErrors(t *harnessTest) {
reissueRequest.Asset.NewGroupedAsset = true
reissueRequest.Asset.GroupedAsset = false
_, err = t.tapd.MintAsset(ctxb, reissueRequest)
require.ErrorContains(t.t, err, "must disable emission to specify")
require.ErrorContains(
t.t, err, "must not create new grouped asset to specify",
)

// Restore the correct flags for a new grouped asset.
reissueRequest.Asset.NewGroupedAsset = false
Expand Down
19 changes: 11 additions & 8 deletions rpcserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -443,19 +443,19 @@ func (r *rpcServer) MintAsset(ctx context.Context,
// Using a specific group key or anchor implies disabling emission.
case req.Asset.NewGroupedAsset:
if specificGroupKey || specificGroupAnchor {
return nil, fmt.Errorf("must disable emission to " +
"specify a group")
return nil, fmt.Errorf("must not create new grouped " +
"asset to specify an existing group")
}

// A group tapscript root cannot be specified if emission is disabled.
case !req.Asset.NewGroupedAsset && groupTapscriptRootSize != 0:
return nil, fmt.Errorf("cannot specify a group tapscript root" +
"with emission disabled")
"when not creating a new grouped asset")

// A group internal key cannot be specified if emission is disabled.
case !req.Asset.NewGroupedAsset && specificGroupInternalKey:
return nil, fmt.Errorf("cannot specify a group internal key" +
"with emission disabled")
"when not creating a new grouped asset")

// If the asset is intended to be part of an existing group, a group key
// or anchor must be specified, but not both. Neither a group tapscript
Expand All @@ -473,12 +473,14 @@ func (r *rpcServer) MintAsset(ctx context.Context,

if groupTapscriptRootSize != 0 {
return nil, fmt.Errorf("cannot specify a group " +
"tapscript root with emission disabled")
"tapscript root when not creating a new " +
"grouped asset")
}

if specificGroupInternalKey {
return nil, fmt.Errorf("cannot specify a group " +
"internal key with emission disabled")
"internal key when not creating a new " +
"grouped asset")
}

// A group was specified without GroupedAsset being set.
Expand Down Expand Up @@ -608,8 +610,9 @@ func (r *rpcServer) MintAsset(ctx context.Context,
}

rpcsLog.Infof("[MintAsset]: version=%v, type=%v, name=%v, amt=%v, "+
"enable_emission=%v", seedling.AssetVersion, seedling.AssetType,
seedling.AssetName, seedling.Amount, seedling.EnableEmission)
"new_grouped_asset=%v", seedling.AssetVersion,
seedling.AssetType, seedling.AssetName, seedling.Amount,
seedling.EnableEmission)

if scriptKey != nil {
seedling.ScriptKey = *scriptKey
Expand Down
8 changes: 4 additions & 4 deletions tapgarden/batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ func (m *MintingBatch) validateGroupAnchor(s *Seedling) error {
s.GroupAnchor)
}
if !anchor.EnableEmission {
return fmt.Errorf("group anchor %v has emission disabled",
return fmt.Errorf("group anchor %v isn't starting a new group",
*s.GroupAnchor)
}

Expand Down Expand Up @@ -414,9 +414,9 @@ func (m *MintingBatch) validateUniCommitment(newSeedling Seedling) error {
// seedling has the universe commitment flag enabled, it must
// specify a re-issuable asset group key.
if !newSeedling.EnableEmission {
return fmt.Errorf("the emission flag must be enabled " +
"for the first asset in a batch with the " +
"universe commitment flag enabled")
return fmt.Errorf("the 'new grouped asset' flag must " +
"be enabled for the first asset in a batch " +
"with the universe commitment flag enabled")
}

if !newSeedling.HasGroupKey() {
Expand Down
11 changes: 8 additions & 3 deletions tapgarden/planter.go
Original file line number Diff line number Diff line change
Expand Up @@ -2668,14 +2668,19 @@ func (c *ChainPlanter) prepAssetSeedling(ctx context.Context,
// If a group internal key or tapscript root is specified, emission must
// also be enabled.
if !req.EnableEmission {
if req.GroupInternalKey != nil {
// For re-issuing grouped assets or regular (non-grouped)
// assets, the group internal key shouldn't be set. It is,
// however, set for re-issuance with an external key, because
// the internal group key is the key we compare the external key
// against.
if req.GroupInternalKey != nil && req.ExternalKey.IsNone() {
return fmt.Errorf("cannot specify group internal key " +
"without enabling emission")
"without creating a new grouped asset")
}

if req.GroupTapscriptRoot != nil {
return fmt.Errorf("cannot specify group tapscript " +
"root without enabling emission")
"root without creating a new grouped asset")
}
}

Expand Down
35 changes: 33 additions & 2 deletions tapgarden/seedling.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,12 +183,43 @@ func (c Seedling) validateFields() error {
func (c Seedling) validateGroupKey(group asset.AssetGroup,
anchorMeta *proof.MetaReveal) error {

// We must be able to sign with the group key.
if !group.GroupKey.IsLocal() {
// If an external key isn't specified but the actual group key used
// isn't local to this daemon, we won't be able to sign with it.
if c.ExternalKey.IsNone() && !group.GroupKey.IsLocal() {
groupKeyBytes := c.GroupInfo.GroupPubKey.SerializeCompressed()
return fmt.Errorf("can't sign with group key %x", groupKeyBytes)
}

// If there is an external key defined, we need to check that it matches
// the group key.
err := fn.MapOptionZ(
c.ExternalKey, func(extKey asset.ExternalKey) error {
if group.GroupKey == nil {
return fmt.Errorf("group key is nil")
}

if group.GroupKey.RawKey.PubKey == nil {
return fmt.Errorf("group raw key is nil")
}

pk, err := extKey.PubKey()
if err != nil {
return fmt.Errorf("error getting external "+
"key: %w", err)
}

if !pk.IsEqual(group.RawKey.PubKey) {
return fmt.Errorf("external key does not " +
"match group key")
}

return nil
},
)
if err != nil {
return fmt.Errorf("error validating external key: %w", err)
}

// The seedling asset type must match the group asset type.
if c.AssetType != group.Genesis.Type {
return fmt.Errorf("seedling type does not match "+
Expand Down
Loading