Skip to content

Commit

Permalink
tapsend: remove now unused functions
Browse files Browse the repository at this point in the history
We are now validating the input amount and types when creating the
allocations and no longer need this function.
  • Loading branch information
guggero committed Feb 26, 2025
1 parent 7a70bb4 commit ee66eb9
Show file tree
Hide file tree
Showing 2 changed files with 0 additions and 320 deletions.
102 changes: 0 additions & 102 deletions tapsend/send.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,108 +277,6 @@ func DescribeAddrs(addrs []*address.Tap) (*FundingDescriptor, error) {
return desc, nil
}

// AssetFromTapCommitment uses a script key to extract an asset from a given
// Taproot Asset commitment.
func AssetFromTapCommitment(tapCommitment *commitment.TapCommitment,
specifier asset.Specifier,
inputScriptKey btcec.PublicKey) (*asset.Asset, error) {

// The top-level Taproot Asset tree must have a non-empty asset tree at
// the leaf specified by the funding descriptor's asset (group) specific
// commitment locator.
tapKey := asset.TapCommitmentKey(specifier)
assetCommitments := tapCommitment.Commitments()
assetCommitment, ok := assetCommitments[tapKey]
if !ok {
return nil, fmt.Errorf("input commitment does "+
"not contain asset=%s: %w", &specifier,
ErrMissingInputAsset)
}

// Determine whether issuance is disabled for the asset.
issuanceDisabled := !specifier.HasGroupPubKey()

assetId, err := specifier.UnwrapIdOrErr()
if err != nil {
return nil, fmt.Errorf("asset from tap commitment: %w", err)
}

// The asset tree must have a non-empty Asset at the location
// specified by the sender's script key.
assetCommitmentKey := asset.AssetCommitmentKey(
assetId, &inputScriptKey, issuanceDisabled,
)
inputAsset, ok := assetCommitment.Asset(assetCommitmentKey)
if !ok {
return nil, fmt.Errorf("input commitment does not "+
"contain leaf with script_key=%x: %w",
inputScriptKey.SerializeCompressed(),
ErrMissingInputAsset)
}

return inputAsset, nil
}

// ValidateInputs validates a set of inputs against a funding request. It
// returns true if the inputs would be spent fully, otherwise false.
func ValidateInputs(inputCommitments tappsbt.InputCommitments,
expectedAssetType asset.Type, specifier asset.Specifier,
outputAmount uint64) (bool, error) {

// Extract the input assets from the input commitments.
inputAssets := make([]*asset.Asset, 0, len(inputCommitments))
for prevID := range inputCommitments {
tapCommitment := inputCommitments[prevID]
senderScriptKey, err := prevID.ScriptKey.ToPubKey()
if err != nil {
return false, fmt.Errorf("unable to parse sender "+
"script key: %v", err)
}

// Gain the asset that we'll use as an input and in the process
// validate the selected input and commitment.
inputAsset, err := AssetFromTapCommitment(
tapCommitment, specifier, *senderScriptKey,
)
if err != nil {
return false, err
}

// Ensure input asset has the expected type.
if inputAsset.Type != expectedAssetType {
return false, fmt.Errorf("unexpected input asset type")
}

inputAssets = append(inputAssets, inputAsset)
}

// Validate total amount of input assets and determine full value spend
// status.
var isFullValueSpend bool
switch expectedAssetType {
case asset.Normal:
// Sum the total amount of the input assets.
var totalInputsAmount uint64
for _, inputAsset := range inputAssets {
totalInputsAmount += inputAsset.Amount
}

// Ensure that the input assets are sufficient to cover the amount
// being sent.
if totalInputsAmount < outputAmount {
return false, ErrInsufficientInputAssets
}

// Check if the input assets are fully spent.
isFullValueSpend = totalInputsAmount == outputAmount

case asset.Collectible:
isFullValueSpend = true
}

return isFullValueSpend, nil
}

// ValidateCommitmentKeysUnique makes sure the outputs of a set of virtual
// packets don't lead to collisions in and of the trees (e.g. two asset outputs
// with the same asset ID and script key in the same anchor output) or with
Expand Down
218 changes: 0 additions & 218 deletions tapsend/send_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1895,224 +1895,6 @@ func TestProofVerifyFullValueSplit(t *testing.T) {
require.NoError(t, err)
}

// TestAddressValidInput tests edge cases around validating inputs for asset
// transfers with isValidInput.
func TestAddressValidInput(t *testing.T) {
t.Parallel()

for _, testCase := range addressValidInputTestCases {
success := t.Run(testCase.name, func(t *testing.T) {
inputAsset, checkedInputAsset, err := testCase.f(t)
require.ErrorIs(t, err, testCase.err)
if testCase.err == nil {
require.True(t, inputAsset.DeepEqual(
checkedInputAsset,
))
}
})
if !success {
return
}
}
}

func addrToFundDesc(addr address.Tap) *tapsend.FundingDescriptor {
assetSpecifier := asset.NewSpecifierOptionalGroupPubKey(
addr.AssetID, addr.GroupKey,
)

return &tapsend.FundingDescriptor{
AssetSpecifier: assetSpecifier,
Amount: addr.Amount,
}
}

type addressValidInputTestCase struct {
name string
f func(t *testing.T) (*asset.Asset, *asset.Asset, error)
err error
}

var addressValidInputTestCases = []addressValidInputTestCase{{
name: "valid normal",
f: func(t *testing.T) (*asset.Asset, *asset.Asset, error) {
state := initSpendScenario(t)
fundDesc := addrToFundDesc(state.address1)

inputAsset, err := tapsend.AssetFromTapCommitment(
&state.asset1TapTree, fundDesc.AssetSpecifier,
state.spenderScriptKey,
)
if err != nil {
return nil, nil, err
}

fullValue, err := tapsend.ValidateInputs(
tappsbt.InputCommitments{
state.asset1PrevID: &state.asset1TapTree,
}, inputAsset.Type, fundDesc.AssetSpecifier,
fundDesc.Amount,
)
if err != nil {
return nil, nil, err
}
require.True(t, fullValue)

return &state.asset1, inputAsset, nil
},
err: nil,
}, {
name: "valid collectible with group key",
f: func(t *testing.T) (*asset.Asset, *asset.Asset, error) {
state := initSpendScenario(t)
fundDesc := addrToFundDesc(state.address1CollectGroup)

inputAsset, err := tapsend.AssetFromTapCommitment(
&state.asset1CollectGroupTapTree,
fundDesc.AssetSpecifier, state.spenderScriptKey,
)
if err != nil {
return nil, nil, err
}

inputCommitment := &state.asset1CollectGroupTapTree
fullValue, err := tapsend.ValidateInputs(
tappsbt.InputCommitments{
state.asset1CollectGroupPrevID: inputCommitment,
}, inputAsset.Type, fundDesc.AssetSpecifier,
fundDesc.Amount,
)
if err != nil {
return nil, nil, err
}
require.True(t, fullValue)

return &state.asset1CollectGroup, inputAsset, nil
},
err: nil,
}, {
name: "valid asset split",
f: func(t *testing.T) (*asset.Asset, *asset.Asset, error) {
state := initSpendScenario(t)
fundDesc := addrToFundDesc(state.address1)

inputAsset, err := tapsend.AssetFromTapCommitment(
&state.asset2TapTree, fundDesc.AssetSpecifier,
state.spenderScriptKey,
)
if err != nil {
return nil, nil, err
}

fullValue, err := tapsend.ValidateInputs(
tappsbt.InputCommitments{
state.asset2PrevID: &state.asset2TapTree,
}, inputAsset.Type, fundDesc.AssetSpecifier,
fundDesc.Amount,
)
if err != nil {
return nil, nil, err
}
require.False(t, fullValue)

return &state.asset2, inputAsset, nil
},
err: nil,
}, {
name: "normal with insufficient amount",
f: func(t *testing.T) (*asset.Asset, *asset.Asset, error) {
state := initSpendScenario(t)
fundDesc := addrToFundDesc(state.address2)

inputAsset, err := tapsend.AssetFromTapCommitment(
&state.asset1TapTree, fundDesc.AssetSpecifier,
state.spenderScriptKey,
)
if err != nil {
return nil, nil, err
}

fullValue, err := tapsend.ValidateInputs(
tappsbt.InputCommitments{
state.asset1PrevID: &state.asset1TapTree,
}, inputAsset.Type, fundDesc.AssetSpecifier,
fundDesc.Amount,
)
if err != nil {
return nil, nil, err
}
require.True(t, fullValue)

return &state.asset1, inputAsset, nil
},
err: tapsend.ErrInsufficientInputAssets,
}, {
name: "collectible with missing input asset",
f: func(t *testing.T) (*asset.Asset, *asset.Asset, error) {
state := initSpendScenario(t)
fundDesc := addrToFundDesc(state.address1CollectGroup)

inputAsset, err := tapsend.AssetFromTapCommitment(
&state.asset1TapTree, fundDesc.AssetSpecifier,
state.spenderScriptKey,
)
if err != nil {
return nil, nil, err
}

fullValue, err := tapsend.ValidateInputs(
tappsbt.InputCommitments{
state.asset1PrevID: &state.asset1TapTree,
}, inputAsset.Type, fundDesc.AssetSpecifier,
fundDesc.Amount,
)
if err != nil {
return nil, nil, err
}
require.False(t, fullValue)

return &state.asset1, inputAsset, nil
},
err: tapsend.ErrMissingInputAsset,
}, {
name: "normal with bad sender script key",
f: func(t *testing.T) (*asset.Asset, *asset.Asset, error) {
state := initSpendScenario(t)

address1testnet, err := address.New(
address.V0, state.genesis1, nil, nil,
state.receiverPubKey, state.receiverPubKey,
state.normalAmt1, nil, &address.TestNet3Tap,
address.RandProofCourierAddr(t),
)
require.NoError(t, err)

fundDesc := addrToFundDesc(*address1testnet)

inputAsset, err := tapsend.AssetFromTapCommitment(
&state.asset1TapTree, fundDesc.AssetSpecifier,
state.receiverPubKey,
)
if err != nil {
return nil, nil, err
}

fullValue, err := tapsend.ValidateInputs(
tappsbt.InputCommitments{
state.asset1PrevID: &state.asset1TapTree,
}, inputAsset.Type, fundDesc.AssetSpecifier,
fundDesc.Amount,
)
if err != nil {
return nil, nil, err
}
require.True(t, fullValue)

return &state.asset1, inputAsset, nil
},
err: tapsend.ErrMissingInputAsset,
}}

// TestPayToAddrScript tests edge cases around creating a P2TR script with
// PayToAddrScript.
func TestPayToAddrScript(t *testing.T) {
Expand Down

0 comments on commit ee66eb9

Please sign in to comment.