Skip to content

Commit f8f67b1

Browse files
committed
taprpc+rpcserver: allow user to set script key type
Specifying a script key as known now requires the user to set a specific type.
1 parent 914f109 commit f8f67b1

File tree

7 files changed

+990
-718
lines changed

7 files changed

+990
-718
lines changed

rpcserver.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7914,11 +7914,21 @@ func (r *rpcServer) DeclareScriptKey(ctx context.Context,
79147914
}
79157915

79167916
// Because we've been given the key over the RPC interface, we can't be
7917-
// 100% sure of the type. But we can make a best effort guess based on
7918-
// the fields the user has set.
7919-
keyType := scriptKey.GuessType()
7917+
// 100% sure of the type, if it wasn't declared. But we can make a
7918+
// best-effort guess based on the fields the user has set. This is a
7919+
// no-op if the type is already set.
7920+
scriptKey.Type = scriptKey.GuessType()
79207921

7921-
err = r.cfg.TapAddrBook.InsertScriptKey(ctx, *scriptKey, true, keyType)
7922+
// The user is declaring the key, so they should know what type it is.
7923+
// So if they didn't set it, and it wasn't an obvious one, we'll require
7924+
// them to set it.
7925+
if scriptKey.Type == asset.ScriptKeyUnknown {
7926+
return nil, fmt.Errorf("script key type must be set")
7927+
}
7928+
7929+
err = r.cfg.TapAddrBook.InsertScriptKey(
7930+
ctx, *scriptKey, true, scriptKey.Type,
7931+
)
79227932
if err != nil {
79237933
return nil, fmt.Errorf("error inserting script key: %w", err)
79247934
}

taprpc/assetwalletrpc/assetwallet.swagger.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,9 +1027,26 @@
10271027
"type": "string",
10281028
"format": "byte",
10291029
"description": "The optional Taproot tweak to apply to the above internal key. If this is\nempty then a BIP-86 style tweak is applied to the internal key."
1030+
},
1031+
"type": {
1032+
"$ref": "#/definitions/taprpcScriptKeyType",
1033+
"description": "The type of the script key, as declared by the user."
10301034
}
10311035
}
10321036
},
1037+
"taprpcScriptKeyType": {
1038+
"type": "string",
1039+
"enum": [
1040+
"SCRIPT_KEY_UNKNOWN",
1041+
"SCRIPT_KEY_BIP86",
1042+
"SCRIPT_KEY_SCRIPT_PATH_EXTERNAL",
1043+
"SCRIPT_KEY_BURN",
1044+
"SCRIPT_KEY_TOMBSTONE",
1045+
"SCRIPT_KEY_CHANNEL"
1046+
],
1047+
"default": "SCRIPT_KEY_UNKNOWN",
1048+
"description": " - SCRIPT_KEY_UNKNOWN: The type of script key is not known. This should only be stored for assets\nwhere we don't know the internal key of the script key (e.g. for\nimported proofs).\n - SCRIPT_KEY_BIP86: The script key is a normal BIP-86 key. This means that the internal key is\nturned into a Taproot output key by applying a BIP-86 tweak to it.\n - SCRIPT_KEY_SCRIPT_PATH_EXTERNAL: The script key is a key that contains a script path that is defined by the\nuser and is therefore external to the tapd wallet. Spending this key\nrequires providing a specific witness and must be signed through the vPSBT\nsigning flow.\n - SCRIPT_KEY_BURN: The script key is a specific un-spendable key that indicates a burnt asset.\nAssets with this key type can never be spent again, as a burn key is a\ntweaked NUMS key that nobody knows the private key for.\n - SCRIPT_KEY_TOMBSTONE: The script key is a specific un-spendable key that indicates a tombstone\noutput. This is only the case for zero-value assets that result from a\nnon-interactive (TAP address) send where no change was left over.\n - SCRIPT_KEY_CHANNEL: The script key is used for an asset that resides within a Taproot Asset\nChannel. That means the script key is either a funding key (OP_TRUE), a\ncommitment output key (to_local, to_remote, htlc), or a HTLC second-level\ntransaction output key. Keys related to channels are not shown in asset\nbalances (unless specifically requested) and are never used for coin\nselection."
1049+
},
10331050
"taprpcSendAssetResponse": {
10341051
"type": "object",
10351052
"properties": {

taprpc/marshal.go

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,14 @@ func UnmarshalKeyDescriptor(rpcDesc *KeyDescriptor) (keychain.KeyDescriptor,
8585
// UnmarshalScriptKey parses the RPC script key into the native counterpart.
8686
func UnmarshalScriptKey(rpcKey *ScriptKey) (*asset.ScriptKey, error) {
8787
var (
88-
scriptKey asset.ScriptKey
89-
err error
88+
scriptKey = asset.ScriptKey{
89+
TweakedScriptKey: &asset.TweakedScriptKey{
90+
// The tweak is optional, if it's empty it means
91+
// the key is derived using BIP-0086.
92+
Tweak: rpcKey.TapTweak,
93+
},
94+
}
95+
err error
9096
)
9197

9298
// The script public key is a Taproot key, so 32-byte x-only.
@@ -98,17 +104,15 @@ func UnmarshalScriptKey(rpcKey *ScriptKey) (*asset.ScriptKey, error) {
98104
// The key descriptor is optional for script keys that are completely
99105
// independent of the backing wallet.
100106
if rpcKey.KeyDesc != nil {
101-
keyDesc, err := UnmarshalKeyDescriptor(rpcKey.KeyDesc)
107+
scriptKey.RawKey, err = UnmarshalKeyDescriptor(rpcKey.KeyDesc)
102108
if err != nil {
103109
return nil, err
104110
}
105-
scriptKey.TweakedScriptKey = &asset.TweakedScriptKey{
106-
RawKey: keyDesc,
111+
}
107112

108-
// The tweak is optional, if it's empty it means the key
109-
// is derived using BIP-0086.
110-
Tweak: rpcKey.TapTweak,
111-
}
113+
scriptKey.Type, err = UnmarshalScriptKeyType(rpcKey.Type)
114+
if err != nil {
115+
return nil, err
112116
}
113117

114118
return &scriptKey, nil
@@ -125,11 +129,63 @@ func MarshalScriptKey(scriptKey asset.ScriptKey) *ScriptKey {
125129
scriptKey.TweakedScriptKey.RawKey,
126130
)
127131
rpcScriptKey.TapTweak = scriptKey.TweakedScriptKey.Tweak
132+
rpcScriptKey.Type = MarshalScriptKeyType(scriptKey.Type)
128133
}
129134

130135
return rpcScriptKey
131136
}
132137

138+
// UnmarshalScriptKeyType parses the script key type from the RPC variant.
139+
func UnmarshalScriptKeyType(rpcType ScriptKeyType) (asset.ScriptKeyType,
140+
error) {
141+
142+
switch rpcType {
143+
case ScriptKeyType_SCRIPT_KEY_UNKNOWN:
144+
return asset.ScriptKeyUnknown, nil
145+
146+
case ScriptKeyType_SCRIPT_KEY_BIP86:
147+
return asset.ScriptKeyBip86, nil
148+
149+
case ScriptKeyType_SCRIPT_KEY_SCRIPT_PATH_EXTERNAL:
150+
return asset.ScriptKeyScriptPathExternal, nil
151+
152+
case ScriptKeyType_SCRIPT_KEY_BURN:
153+
return asset.ScriptKeyBurn, nil
154+
155+
case ScriptKeyType_SCRIPT_KEY_TOMBSTONE:
156+
return asset.ScriptKeyTombstone, nil
157+
158+
case ScriptKeyType_SCRIPT_KEY_CHANNEL:
159+
return asset.ScriptKeyScriptPathChannel, nil
160+
161+
default:
162+
return 0, fmt.Errorf("unknown script key type: %v", rpcType)
163+
}
164+
}
165+
166+
// MarshalScriptKeyType marshals the script key type from the RPC variant.
167+
func MarshalScriptKeyType(typ asset.ScriptKeyType) ScriptKeyType {
168+
switch typ {
169+
case asset.ScriptKeyBip86:
170+
return ScriptKeyType_SCRIPT_KEY_BIP86
171+
172+
case asset.ScriptKeyScriptPathExternal:
173+
return ScriptKeyType_SCRIPT_KEY_SCRIPT_PATH_EXTERNAL
174+
175+
case asset.ScriptKeyBurn:
176+
return ScriptKeyType_SCRIPT_KEY_BURN
177+
178+
case asset.ScriptKeyTombstone:
179+
return ScriptKeyType_SCRIPT_KEY_TOMBSTONE
180+
181+
case asset.ScriptKeyScriptPathChannel:
182+
return ScriptKeyType_SCRIPT_KEY_CHANNEL
183+
184+
default:
185+
return ScriptKeyType_SCRIPT_KEY_UNKNOWN
186+
}
187+
}
188+
133189
// UnmarshalAssetVersion parses an asset version from the RPC variant.
134190
func UnmarshalAssetVersion(version AssetVersion) (asset.Version, error) {
135191
// For now, we'll only support two asset versions. The ones in the

taprpc/mintrpc/mint.swagger.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,9 +899,26 @@
899899
"type": "string",
900900
"format": "byte",
901901
"description": "The optional Taproot tweak to apply to the above internal key. If this is\nempty then a BIP-86 style tweak is applied to the internal key."
902+
},
903+
"type": {
904+
"$ref": "#/definitions/taprpcScriptKeyType",
905+
"description": "The type of the script key, as declared by the user."
902906
}
903907
}
904908
},
909+
"taprpcScriptKeyType": {
910+
"type": "string",
911+
"enum": [
912+
"SCRIPT_KEY_UNKNOWN",
913+
"SCRIPT_KEY_BIP86",
914+
"SCRIPT_KEY_SCRIPT_PATH_EXTERNAL",
915+
"SCRIPT_KEY_BURN",
916+
"SCRIPT_KEY_TOMBSTONE",
917+
"SCRIPT_KEY_CHANNEL"
918+
],
919+
"default": "SCRIPT_KEY_UNKNOWN",
920+
"description": " - SCRIPT_KEY_UNKNOWN: The type of script key is not known. This should only be stored for assets\nwhere we don't know the internal key of the script key (e.g. for\nimported proofs).\n - SCRIPT_KEY_BIP86: The script key is a normal BIP-86 key. This means that the internal key is\nturned into a Taproot output key by applying a BIP-86 tweak to it.\n - SCRIPT_KEY_SCRIPT_PATH_EXTERNAL: The script key is a key that contains a script path that is defined by the\nuser and is therefore external to the tapd wallet. Spending this key\nrequires providing a specific witness and must be signed through the vPSBT\nsigning flow.\n - SCRIPT_KEY_BURN: The script key is a specific un-spendable key that indicates a burnt asset.\nAssets with this key type can never be spent again, as a burn key is a\ntweaked NUMS key that nobody knows the private key for.\n - SCRIPT_KEY_TOMBSTONE: The script key is a specific un-spendable key that indicates a tombstone\noutput. This is only the case for zero-value assets that result from a\nnon-interactive (TAP address) send where no change was left over.\n - SCRIPT_KEY_CHANNEL: The script key is used for an asset that resides within a Taproot Asset\nChannel. That means the script key is either a funding key (OP_TRUE), a\ncommitment output key (to_local, to_remote, htlc), or a HTLC second-level\ntransaction output key. Keys related to channels are not shown in asset\nbalances (unless specifically requested) and are never used for coin\nselection."
921+
},
905922
"taprpcTapBranch": {
906923
"type": "object",
907924
"properties": {

0 commit comments

Comments
 (0)