@@ -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.
@@ -1013,6 +1057,9 @@ type TweakedScriptKey struct {
10131057 // flag has is that assets with a declared key are shown in the asset
10141058 // list/balance.
10151059 DeclaredKnown bool
1060+
1061+ // Type is the type of script key that is being used.
1062+ Type ScriptKeyType
10161063}
10171064
10181065// IsEqual returns true is this tweaked script key is exactly equivalent to the
@@ -1098,15 +1145,55 @@ func (s *ScriptKey) HasScriptPath() bool {
10981145 return s .TweakedScriptKey != nil && len (s .TweakedScriptKey .Tweak ) > 0
10991146}
11001147
1148+ // DetermineType attempts to determine the type of the script key based on the
1149+ // information available. This method will only return ScriptKeyUnknown if the
1150+ // following condition is met:
1151+ // - The script key doesn't have a script path, but the final Taproot output
1152+ // key doesn't match a BIP-0086 key derived from the internal key. This will
1153+ // be the case for "foreign" script keys we import from proofs, where we set
1154+ // the internal key to the same key as the tweaked script key (because we
1155+ // don't know the internal key, as it's not part of the proof encoding).
1156+ func (s * ScriptKey ) DetermineType () ScriptKeyType {
1157+ // If we have an explicit script key type set, we can return that.
1158+ if s .TweakedScriptKey != nil &&
1159+ s .TweakedScriptKey .Type != ScriptKeyUnknown {
1160+
1161+ return s .TweakedScriptKey .Type
1162+ }
1163+
1164+ // If there is a known tweak, then we know that this is a script path
1165+ // key. We never return the channel type, since those keys should always
1166+ // be declared properly, and we never should need to guess their type.
1167+ if s .HasScriptPath () {
1168+ return ScriptKeyScriptPathExternal
1169+ }
1170+
1171+ // Is it the known NUMS key? Then this is a tombstone output.
1172+ if s .PubKey != nil && s .PubKey .IsEqual (NUMSPubKey ) {
1173+ return ScriptKeyTombstone
1174+ }
1175+
1176+ // Do we know the internal key? Then we can check whether it is a
1177+ // BIP-0086 key.
1178+ if s .PubKey != nil && s .TweakedScriptKey != nil &&
1179+ s .TweakedScriptKey .RawKey .PubKey != nil {
1180+
1181+ bip86 := NewScriptKeyBip86 (s .TweakedScriptKey .RawKey )
1182+ if bip86 .PubKey .IsEqual (s .PubKey ) {
1183+ return ScriptKeyBip86
1184+ }
1185+ }
1186+
1187+ return ScriptKeyUnknown
1188+ }
1189+
11011190// NewScriptKey constructs a ScriptKey with only the publicly available
11021191// information. This resulting key may or may not have a tweak applied to it.
11031192func NewScriptKey (key * btcec.PublicKey ) ScriptKey {
11041193 // Since we'll never query lnd for a tweaked key, it doesn't matter if
11051194 // we lose the parity information here. And this will only ever be
11061195 // serialized on chain in a 32-bit representation as well.
1107- key , _ = schnorr .ParsePubKey (
1108- schnorr .SerializePubKey (key ),
1109- )
1196+ key , _ = schnorr .ParsePubKey (schnorr .SerializePubKey (key ))
11101197 return ScriptKey {
11111198 PubKey : key ,
11121199 }
@@ -1118,9 +1205,7 @@ func NewScriptKey(key *btcec.PublicKey) ScriptKey {
11181205func NewScriptKeyBip86 (rawKey keychain.KeyDescriptor ) ScriptKey {
11191206 // Tweak the script key BIP-0086 style (such that we only commit to the
11201207 // internal key when signing).
1121- tweakedPubKey := txscript .ComputeTaprootKeyNoScript (
1122- rawKey .PubKey ,
1123- )
1208+ tweakedPubKey := txscript .ComputeTaprootKeyNoScript (rawKey .PubKey )
11241209
11251210 // Since we'll never query lnd for a tweaked key, it doesn't matter if
11261211 // we lose the parity information here. And this will only ever be
@@ -1133,6 +1218,7 @@ func NewScriptKeyBip86(rawKey keychain.KeyDescriptor) ScriptKey {
11331218 PubKey : tweakedPubKey ,
11341219 TweakedScriptKey : & TweakedScriptKey {
11351220 RawKey : rawKey ,
1221+ Type : ScriptKeyBip86 ,
11361222 },
11371223 }
11381224}
@@ -1527,6 +1613,7 @@ func (a *Asset) Copy() *Asset {
15271613 if a .ScriptKey .TweakedScriptKey != nil {
15281614 assetCopy .ScriptKey .TweakedScriptKey = & TweakedScriptKey {
15291615 DeclaredKnown : a .ScriptKey .DeclaredKnown ,
1616+ Type : a .ScriptKey .Type ,
15301617 }
15311618 assetCopy .ScriptKey .RawKey = a .ScriptKey .RawKey
15321619
0 commit comments