Skip to content

Commit

Permalink
vm: test group anchors with script witnesses
Browse files Browse the repository at this point in the history
  • Loading branch information
jharveyb committed Oct 4, 2023
1 parent c7cb547 commit e0fb436
Showing 1 changed file with 136 additions and 5 deletions.
141 changes: 136 additions & 5 deletions vm/vm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import (

"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/schnorr"
"github.com/btcsuite/btcd/btcutil/psbt"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcwallet/waddrmgr"
"github.com/lightninglabs/lndclient"
"github.com/lightninglabs/taproot-assets/asset"
"github.com/lightninglabs/taproot-assets/commitment"
"github.com/lightninglabs/taproot-assets/internal/test"
Expand Down Expand Up @@ -46,6 +48,73 @@ func randAsset(t *testing.T, assetType asset.Type,
)
}

func assetCustomGroupKey(t *testing.T, useHashLock, BIP86, keySpend, valid bool,
assetType asset.Type) *asset.Asset {

t.Helper()

genesis := asset.RandGenesis(t, assetType)
genID := genesis.ID()
scriptKey := asset.RandScriptKey(t)
protoAsset := asset.RandAssetWithValues(t, genesis, nil, scriptKey)

groupPrivKey := test.RandPrivKey(t)
groupInternalKey := groupPrivKey.PubKey()
genSigner := asset.NewMockGenesisSigner(groupPrivKey)
genBuilder := asset.MockGroupTxBuilder{}

// Manually create and use the singly tweaked key here, to match the
// signing behavior later when using the signing descriptor.
groupSinglyTweakedKey := input.TweakPubKeyWithTweak(
groupInternalKey, genID[:],
)
_, _, tapLeaf, tapTweak, scriptWitness := buildTapscriptTree(
t, useHashLock, valid, groupSinglyTweakedKey,
)

// Default to a BIP-0086 style group key.
signDesc := lndclient.SignDescriptor{
KeyDesc: test.PubToKeyDesc(groupInternalKey),
}

// Update the signing descriptor and group key derivation arguments
// to match the requested group key type.
if BIP86 && keySpend {
require.Fail(t, "Cannot have both BIP 86 and key spend group "+
"key types")
}

switch {
case BIP86:
// Unset the created script and script witness.
tapLeaf = nil
scriptWitness = nil

case keySpend:
// Set a tapscipt root but unset the created script and witness.
signDesc.TapTweak = tapTweak
tapLeaf = nil
scriptWitness = nil

default:
// For a script spend, we only need to set the tapscript root
// in the sign descriptor; the script and script witness are
// already populated.
signDesc.TapTweak = tapTweak
}

groupKey, err := asset.DeriveCustomGroupKey(
genSigner, &genBuilder, signDesc, tapLeaf, scriptWitness,
genesis, protoAsset,
)
require.NoError(t, err)

return asset.NewAssetNoErr(
t, genesis, protoAsset.Amount, protoAsset.LockTime,
protoAsset.RelativeLockTime, scriptKey, groupKey,
)
}

func genTaprootKeySpend(t *testing.T, privKey btcec.PrivateKey,
virtualTx *wire.MsgTx, input *asset.Asset, idx uint32) wire.TxWitness {

Expand Down Expand Up @@ -127,6 +196,18 @@ func genesisStateTransition(assetType asset.Type,
}
}

func complexGroupAnchorStateTransition(useHashLock, BIP86, keySpend, valid bool,
assetType asset.Type) stateTransitionFunc {

return func(t *testing.T) (*asset.Asset, commitment.SplitSet,
commitment.InputSet) {

return assetCustomGroupKey(
t, useHashLock, BIP86, keySpend, valid, assetType,
), nil, nil
}
}

func collectibleStateTransition(t *testing.T) (*asset.Asset,
commitment.SplitSet, commitment.InputSet) {

Expand Down Expand Up @@ -401,11 +482,9 @@ func splitCollectibleStateTransition(validRoot bool) stateTransitionFunc {
}
}

func scriptTreeSpendStateTransition(t *testing.T, useHashLock,
valid bool, sigHashType txscript.SigHashType) stateTransitionFunc {

scriptPrivKey := test.RandPrivKey(t)
scriptInternalKey := scriptPrivKey.PubKey()
func buildTapscriptTree(t *testing.T, useHashLock, valid bool,
scriptInternalKey *btcec.PublicKey) (*txscript.TapLeaf,
*waddrmgr.Tapscript, *psbt.TaprootTapLeafScript, []byte, []byte) {

// Let's create a taproot asset script now. This is a hash lock with a
// simple preimage of "foobar".
Expand Down Expand Up @@ -446,6 +525,30 @@ func scriptTreeSpendStateTransition(t *testing.T, useHashLock,
}
}

// Compute the final tapscript root and leaf script needed to create a
// key that includes the above tapscript tree.
tapTweak := testTapScript.ControlBlock.RootHash(
testTapScript.RevealedScript,
)
controlBlockBytes, err := testTapScript.ControlBlock.ToBytes()
require.NoError(t, err)

tapLeaf := &psbt.TaprootTapLeafScript{
ControlBlock: controlBlockBytes,
Script: usedLeaf.Script,
LeafVersion: usedLeaf.LeafVersion,
}

return usedLeaf, testTapScript, tapLeaf, tapTweak, scriptWitness
}

func scriptTreeSpendStateTransition(t *testing.T, useHashLock,
valid bool, sigHashType txscript.SigHashType) stateTransitionFunc {

scriptPrivKey := test.RandPrivKey(t)
usedLeaf, testTapScript, _, _, scriptWitness := buildTapscriptTree(
t, useHashLock, valid, scriptPrivKey.PubKey(),
)
scriptKey, err := testTapScript.TaprootKey()
require.NoError(t, err)

Expand Down Expand Up @@ -520,6 +623,34 @@ func TestVM(t *testing.T) {
f: genesisStateTransition(asset.Collectible, false),
err: newErrKind(ErrInvalidGenesisStateTransition),
},
{
name: "collectible group anchor with BIP86 group key",
f: complexGroupAnchorStateTransition(
true, true, false, false, asset.Collectible,
),
err: nil,
},
{
name: "collectible group anchor with key spend witness",
f: complexGroupAnchorStateTransition(
true, false, true, true, asset.Collectible,
),
err: nil,
},
{
name: "collectible group anchor with hash lock witness",
f: complexGroupAnchorStateTransition(
true, false, false, true, asset.Collectible,
),
err: nil,
},
{
name: "collectible group anchor with sig script witness",
f: complexGroupAnchorStateTransition(
false, false, false, true, asset.Collectible,
),
err: nil,
},
{
name: "invalid split collectible input",
f: splitCollectibleStateTransition(false),
Expand Down

0 comments on commit e0fb436

Please sign in to comment.