@@ -108,6 +108,50 @@ const (
108108 EncodeSegwit
109109)
110110
111+ // ScriptKeyType denotes the type of script key used for an asset. This type is
112+ // serialized to the database, so we don't use iota for the values to ensure
113+ // they don't change by accident.
114+ type ScriptKeyType uint8
115+
116+ const (
117+ // ScriptKeyUnknown is the default script key type used for assets that
118+ // we don't know the type of. This should only be stored for assets
119+ // where we don't know the internal key of the script key (e.g. for
120+ // imported proofs).
121+ ScriptKeyUnknown ScriptKeyType = 0
122+
123+ // ScriptKeyBip86 is the script key type used for assets that use the
124+ // BIP86 style tweak (e.g. an empty tweak).
125+ ScriptKeyBip86 ScriptKeyType = 1
126+
127+ // ScriptKeyScriptPathExternal is the script key type used for assets
128+ // that use a script path that is defined by an external application.
129+ // Keys with script paths are normally not shown in asset balances and
130+ // by default aren't used for coin selection unless specifically
131+ // requested.
132+ ScriptKeyScriptPathExternal ScriptKeyType = 2
133+
134+ // ScriptKeyBurn is the script key type used for assets that are burned
135+ // and not spendable.
136+ ScriptKeyBurn ScriptKeyType = 3
137+
138+ // ScriptKeyTombstone is the script key type used for assets that are
139+ // not spendable and have been marked as tombstones. This is only the
140+ // case for zero-value assets that result from a non-interactive (TAP
141+ // address) send where no change was left over. The script key used for
142+ // this is a NUMS key that is not spendable.
143+ ScriptKeyTombstone ScriptKeyType = 4
144+
145+ // ScriptKeyScriptPathChannel is the script key type used for assets
146+ // that use a script path that is somehow related to Taproot Asset
147+ // Channels. That means the script key is either a funding key
148+ // (OP_TRUE), a commitment output key (to_local, to_remote, htlc), or a
149+ // HTLC second-level transaction output key.
150+ // Keys related to channels are not shown in asset balances (unless
151+ // specifically requested) and are _never_ used for coin selection.
152+ ScriptKeyScriptPathChannel ScriptKeyType = 5
153+ )
154+
111155var (
112156 // ZeroPrevID is the blank prev ID used for genesis assets and also
113157 // asset split leaves.
@@ -1001,6 +1045,9 @@ type TweakedScriptKey struct {
10011045 // flag has is that assets with a declared key are shown in the asset
10021046 // list/balance.
10031047 DeclaredKnown bool
1048+
1049+ // Type is the type of script key that is being used.
1050+ Type ScriptKeyType
10041051}
10051052
10061053// IsEqual returns true is this tweaked script key is exactly equivalent to the
@@ -1086,15 +1133,49 @@ func (s *ScriptKey) HasScriptPath() bool {
10861133 return s .TweakedScriptKey != nil && len (s .TweakedScriptKey .Tweak ) > 0
10871134}
10881135
1136+ // GuessType tries to guess the type of the script key based on the information
1137+ // available.
1138+ func (s * ScriptKey ) GuessType () ScriptKeyType {
1139+ // If we have an explicit script key type set, we can return that.
1140+ if s .TweakedScriptKey != nil &&
1141+ s .TweakedScriptKey .Type != ScriptKeyUnknown {
1142+
1143+ return s .TweakedScriptKey .Type
1144+ }
1145+
1146+ // If there is a known tweak, then we know that this is a script path
1147+ // key. We never return the channel type, since those keys should always
1148+ // be declared properly, and we never should need to guess their type.
1149+ if s .HasScriptPath () {
1150+ return ScriptKeyScriptPathExternal
1151+ }
1152+
1153+ // Is it the known NUMS key? Then this is a tombstone output.
1154+ if s .PubKey != nil && s .PubKey .IsEqual (NUMSPubKey ) {
1155+ return ScriptKeyTombstone
1156+ }
1157+
1158+ // Do we know the internal key? Then we can check whether it is a
1159+ // BIP-0086 key.
1160+ if s .PubKey != nil && s .TweakedScriptKey != nil &&
1161+ s .TweakedScriptKey .RawKey .PubKey != nil {
1162+
1163+ bip86 := NewScriptKeyBip86 (s .TweakedScriptKey .RawKey )
1164+ if bip86 .PubKey .IsEqual (s .PubKey ) {
1165+ return ScriptKeyBip86
1166+ }
1167+ }
1168+
1169+ return ScriptKeyUnknown
1170+ }
1171+
10891172// NewScriptKey constructs a ScriptKey with only the publicly available
10901173// information. This resulting key may or may not have a tweak applied to it.
10911174func NewScriptKey (key * btcec.PublicKey ) ScriptKey {
10921175 // Since we'll never query lnd for a tweaked key, it doesn't matter if
10931176 // we lose the parity information here. And this will only ever be
10941177 // serialized on chain in a 32-bit representation as well.
1095- key , _ = schnorr .ParsePubKey (
1096- schnorr .SerializePubKey (key ),
1097- )
1178+ key , _ = schnorr .ParsePubKey (schnorr .SerializePubKey (key ))
10981179 return ScriptKey {
10991180 PubKey : key ,
11001181 }
@@ -1106,9 +1187,7 @@ func NewScriptKey(key *btcec.PublicKey) ScriptKey {
11061187func NewScriptKeyBip86 (rawKey keychain.KeyDescriptor ) ScriptKey {
11071188 // Tweak the script key BIP-0086 style (such that we only commit to the
11081189 // internal key when signing).
1109- tweakedPubKey := txscript .ComputeTaprootKeyNoScript (
1110- rawKey .PubKey ,
1111- )
1190+ tweakedPubKey := txscript .ComputeTaprootKeyNoScript (rawKey .PubKey )
11121191
11131192 // Since we'll never query lnd for a tweaked key, it doesn't matter if
11141193 // we lose the parity information here. And this will only ever be
@@ -1121,6 +1200,7 @@ func NewScriptKeyBip86(rawKey keychain.KeyDescriptor) ScriptKey {
11211200 PubKey : tweakedPubKey ,
11221201 TweakedScriptKey : & TweakedScriptKey {
11231202 RawKey : rawKey ,
1203+ Type : ScriptKeyBip86 ,
11241204 },
11251205 }
11261206}
@@ -1508,6 +1588,7 @@ func (a *Asset) Copy() *Asset {
15081588 if a .ScriptKey .TweakedScriptKey != nil {
15091589 assetCopy .ScriptKey .TweakedScriptKey = & TweakedScriptKey {
15101590 DeclaredKnown : a .ScriptKey .DeclaredKnown ,
1591+ Type : a .ScriptKey .Type ,
15111592 }
15121593 assetCopy .ScriptKey .RawKey = a .ScriptKey .RawKey
15131594
0 commit comments