From 5395a0fe6b7c637ea3d4cae0eaa645bb04eae438 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 27 Apr 2022 21:05:38 +0200 Subject: [PATCH 01/13] rpcwallet: attempt to locate UTXO information in prev output fetcher Since we might now be given a whole list of UTXOs in the PrevOutputs field of the SignOutputRaw RPC, the previous output fetcher might contain the information we require for the remote signing case. So instead of failing if our wallet doesn't know each input that's being spent, we fall back to the UTXO information contained in the previous outputs. --- lnwallet/rpcwallet/rpcwallet.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lnwallet/rpcwallet/rpcwallet.go b/lnwallet/rpcwallet/rpcwallet.go index a13c72635..4613b5223 100644 --- a/lnwallet/rpcwallet/rpcwallet.go +++ b/lnwallet/rpcwallet/rpcwallet.go @@ -803,6 +803,19 @@ func (r *RPCKeyRing) remoteSign(tx *wire.MsgTx, signDesc *input.SignDescriptor, &txIn.PreviousOutPoint, ) if err != nil { + // Maybe we have an UTXO in the previous output fetcher? + if signDesc.PrevOutputFetcher != nil { + utxo := signDesc.PrevOutputFetcher.FetchPrevOutput( + txIn.PreviousOutPoint, + ) + if utxo != nil && utxo.Value != 0 && + len(utxo.PkScript) > 0 { + + packet.Inputs[idx].WitnessUtxo = utxo + continue + } + } + log.Warnf("No UTXO info found for index %d "+ "(prev_outpoint=%v), won't be able to sign "+ "for taproot output!", idx, From 99cda74f6a4aada0b79950466b30a21077461100 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 27 Apr 2022 21:05:39 +0200 Subject: [PATCH 02/13] input: define new signing method constants --- input/signdescriptor.go | 62 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/input/signdescriptor.go b/input/signdescriptor.go index e3ffc5e24..039523108 100644 --- a/input/signdescriptor.go +++ b/input/signdescriptor.go @@ -3,6 +3,7 @@ package input import ( "encoding/binary" "errors" + "fmt" "io" "github.com/btcsuite/btcd/btcec/v2" @@ -89,6 +90,67 @@ type SignDescriptor struct { InputIndex int } +// SignMethod defines the different ways a signer can sign, given a specific +// input. +type SignMethod uint8 + +const ( + // WitnessV0SignMethod denotes that a SegWit v0 (p2wkh, np2wkh, p2wsh) + // input script should be signed. + WitnessV0SignMethod SignMethod = 0 + + // TaprootKeySpendBIP0086SignMethod denotes that a SegWit v1 (p2tr) + // input should be signed by using the BIP0086 method (commit to + // internal key only). + TaprootKeySpendBIP0086SignMethod SignMethod = 1 + + // TaprootKeySpendSignMethod denotes that a SegWit v1 (p2tr) + // input should be signed by using a given taproot hash to commit to in + // addition to the internal key. + TaprootKeySpendSignMethod SignMethod = 2 + + // TaprootScriptSpendSignMethod denotes that a SegWit v1 (p2tr) input + // should be spent using the script path and that a specific leaf script + // should be signed for. + TaprootScriptSpendSignMethod SignMethod = 3 +) + +// String returns a human-readable representation of the signing method. +func (s SignMethod) String() string { + switch s { + case WitnessV0SignMethod: + return "witness_v0" + case TaprootKeySpendBIP0086SignMethod: + return "taproot_key_spend_bip86" + case TaprootKeySpendSignMethod: + return "taproot_key_spend" + case TaprootScriptSpendSignMethod: + return "taproot_script_spend" + default: + return fmt.Sprintf("unknown<%d>", s) + } +} + +// PkScriptCompatible returns true if the given public key script is compatible +// with the sign method. +func (s SignMethod) PkScriptCompatible(pkScript []byte) bool { + switch s { + // SegWit v0 can be p2wkh, np2wkh, p2wsh. + case WitnessV0SignMethod: + return txscript.IsPayToWitnessPubKeyHash(pkScript) || + txscript.IsPayToWitnessScriptHash(pkScript) || + txscript.IsPayToScriptHash(pkScript) + + case TaprootKeySpendBIP0086SignMethod, TaprootKeySpendSignMethod, + TaprootScriptSpendSignMethod: + + return txscript.IsPayToTaproot(pkScript) + + default: + return false + } +} + // WriteSignDescriptor serializes a SignDescriptor struct into the passed // io.Writer stream. // From 630fc36dcfaee59da3bc22ec2c2a95877acf1279 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 27 Apr 2022 21:05:40 +0200 Subject: [PATCH 03/13] multi: introduce and use new TapTweak and SignMethod fields In this commit, we add a new field `TapTweak` to be used for key path spends. Before this commit, we'd overload the existing `WitnessScript` field to pass this information to the signing context. This was confusing as for tapscript spends, this was the leaf script, which mirrors the other script based spending types. With this new filed, users need to set this to the script root for keypath spends where the output key commits to a real merkle root, and nothing when bip 86 spending is being used. To make the signing even more explicit, we also add a new field called sign_method with an enum type that differentiates between the different segwit v0 and v1 signing methods. Fixes https://github.com/lightningnetwork/lnd/issues/6446. --- input/signdescriptor.go | 21 +- lnrpc/signrpc/signer.pb.go | 712 +++++++++++++++++------------- lnrpc/signrpc/signer.proto | 55 ++- lnrpc/signrpc/signer.swagger.json | 24 +- lnrpc/signrpc/signer_server.go | 90 +++- lntest/itest/lnd_taproot_test.go | 52 ++- lnwallet/btcwallet/signer.go | 14 +- 7 files changed, 610 insertions(+), 358 deletions(-) diff --git a/input/signdescriptor.go b/input/signdescriptor.go index 039523108..17008288b 100644 --- a/input/signdescriptor.go +++ b/input/signdescriptor.go @@ -56,16 +56,29 @@ type SignDescriptor struct { // DoubleTweak, not both. DoubleTweak *btcec.PrivateKey + // TapTweak is a 32-byte value that will be used to derive a taproot + // output public key (or the corresponding private key) from an + // internal key and this tweak. The transformation applied is: + // * outputKey = internalKey + + // tagged_hash("tapTweak", internalKey || tapTweak) + // + // When attempting to sign an output derived via BIP 86, then this + // field should be an empty byte array. + // + // When attempting to sign for the key spend path of an output key that + // commits to an actual script tree, the script root should be used. + TapTweak []byte + // WitnessScript is the full script required to properly redeem the // output. This field should be set to the full script if a p2wsh // output is being signed. For p2wkh it should be set to the hashed // script (PkScript). WitnessScript []byte - // TaprootKeySpend indicates that instead of a witness script being - // spent by the signature that results from this signing request, a - // taproot key spend is performed instead. - TaprootKeySpend bool + // SignMethod specifies how the input should be signed. Depending on the + // selected method, either the TapTweak, WitnessScript or both need to + // be specified. + SignMethod SignMethod // Output is the target output which should be signed. The PkScript and // Value fields within the output should be properly populated, diff --git a/lnrpc/signrpc/signer.pb.go b/lnrpc/signrpc/signer.pb.go index 600b37387..a51c671ad 100644 --- a/lnrpc/signrpc/signer.pb.go +++ b/lnrpc/signrpc/signer.pb.go @@ -20,6 +20,70 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type SignMethod int32 + +const ( + // + //Specifies that a SegWit v0 (p2wkh, np2wkh, p2wsh) input script should be + //signed. + SignMethod_SIGN_METHOD_WITNESS_V0 SignMethod = 0 + // + //Specifies that a SegWit v1 (p2tr) input should be signed by using the + //BIP0086 method (commit to internal key only). + SignMethod_SIGN_METHOD_TAPROOT_KEY_SPEND_BIP0086 SignMethod = 1 + // + //Specifies that a SegWit v1 (p2tr) input should be signed by using a given + //taproot hash to commit to in addition to the internal key. + SignMethod_SIGN_METHOD_TAPROOT_KEY_SPEND SignMethod = 2 + // + //Specifies that a SegWit v1 (p2tr) input should be spent using the script + //path and that a specific leaf script should be signed for. + SignMethod_SIGN_METHOD_TAPROOT_SCRIPT_SPEND SignMethod = 3 +) + +// Enum value maps for SignMethod. +var ( + SignMethod_name = map[int32]string{ + 0: "SIGN_METHOD_WITNESS_V0", + 1: "SIGN_METHOD_TAPROOT_KEY_SPEND_BIP0086", + 2: "SIGN_METHOD_TAPROOT_KEY_SPEND", + 3: "SIGN_METHOD_TAPROOT_SCRIPT_SPEND", + } + SignMethod_value = map[string]int32{ + "SIGN_METHOD_WITNESS_V0": 0, + "SIGN_METHOD_TAPROOT_KEY_SPEND_BIP0086": 1, + "SIGN_METHOD_TAPROOT_KEY_SPEND": 2, + "SIGN_METHOD_TAPROOT_SCRIPT_SPEND": 3, + } +) + +func (x SignMethod) Enum() *SignMethod { + p := new(SignMethod) + *p = x + return p +} + +func (x SignMethod) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SignMethod) Descriptor() protoreflect.EnumDescriptor { + return file_signrpc_signer_proto_enumTypes[0].Descriptor() +} + +func (SignMethod) Type() protoreflect.EnumType { + return &file_signrpc_signer_proto_enumTypes[0] +} + +func (x SignMethod) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use SignMethod.Descriptor instead. +func (SignMethod) EnumDescriptor() ([]byte, []int) { + return file_signrpc_signer_proto_rawDescGZIP(), []int{0} +} + type KeyLocator struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -228,11 +292,20 @@ type SignDescriptor struct { //tweakPriv*sha256(tweakPub || pubKey)) mod N DoubleTweak []byte `protobuf:"bytes,3,opt,name=double_tweak,json=doubleTweak,proto3" json:"double_tweak,omitempty"` // + //The 32 byte input to the taproot tweak derivation that is used to derive + //the output key from an internal key: outputKey = internalKey + + //tagged_hash("tapTweak", internalKey || tapTweak). + // + //When doing a BIP 86 spend, this field can be an empty byte slice. + // + //When doing a normal key path spend, with the output key committing to an + //actual script root, then this field should be: the tapscript root hash. + TapTweak []byte `protobuf:"bytes,10,opt,name=tap_tweak,json=tapTweak,proto3" json:"tap_tweak,omitempty"` + // //The full script required to properly redeem the output. This field will - //only be populated if a p2tr, p2wsh or a p2sh output is being signed. In case - //taproot_key_spend is set to true then this value must correspond to the - //taproot root hash (in case of a tapscript output) or the tap hashed internal - //public key (in case of a BIP-0086 output). + //only be populated if a p2tr, p2wsh or a p2sh output is being signed. If a + //taproot script path spend is being attempted, then this should be the raw + //leaf script. WitnessScript []byte `protobuf:"bytes,4,opt,name=witness_script,json=witnessScript,proto3" json:"witness_script,omitempty"` // //A description of the output being spent. The value and script MUST be @@ -246,11 +319,11 @@ type SignDescriptor struct { //The target input within the transaction that should be signed. InputIndex int32 `protobuf:"varint,8,opt,name=input_index,json=inputIndex,proto3" json:"input_index,omitempty"` // - //Indicates that this should produce a signature that can be used for the key - //spend path of a taproot input. This requires the witness_script field to be - //set to the taproot root hash (in case of a tapscript output) or the tap - //hashed internal public key (in case of a BIP-0086 output). - TaprootKeySpend bool `protobuf:"varint,9,opt,name=taproot_key_spend,json=taprootKeySpend,proto3" json:"taproot_key_spend,omitempty"` + //The sign method specifies how the input should be signed. Depending on the + //method, either the tap_tweak, witness_script or both need to be specified. + //Defaults to SegWit v0 signing to be backward compatible with older RPC + //clients. + SignMethod SignMethod `protobuf:"varint,9,opt,name=sign_method,json=signMethod,proto3,enum=signrpc.SignMethod" json:"sign_method,omitempty"` } func (x *SignDescriptor) Reset() { @@ -306,6 +379,13 @@ func (x *SignDescriptor) GetDoubleTweak() []byte { return nil } +func (x *SignDescriptor) GetTapTweak() []byte { + if x != nil { + return x.TapTweak + } + return nil +} + func (x *SignDescriptor) GetWitnessScript() []byte { if x != nil { return x.WitnessScript @@ -334,11 +414,11 @@ func (x *SignDescriptor) GetInputIndex() int32 { return 0 } -func (x *SignDescriptor) GetTaprootKeySpend() bool { +func (x *SignDescriptor) GetSignMethod() SignMethod { if x != nil { - return x.TaprootKeySpend + return x.SignMethod } - return false + return SignMethod_SIGN_METHOD_WITNESS_V0 } type SignReq struct { @@ -1849,7 +1929,7 @@ var file_signrpc_signer_proto_rawDesc = []byte{ 0x54, 0x78, 0x4f, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6b, 0x5f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, - 0x70, 0x6b, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0xbf, 0x02, 0x0a, 0x0e, 0x53, 0x69, 0x67, + 0x70, 0x6b, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0xe6, 0x02, 0x0a, 0x0e, 0x53, 0x69, 0x67, 0x6e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x12, 0x31, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4b, 0x65, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, @@ -1858,236 +1938,248 @@ var file_signrpc_signer_proto_rawDesc = []byte{ 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x54, 0x77, 0x65, 0x61, 0x6b, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x74, 0x77, 0x65, 0x61, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x54, - 0x77, 0x65, 0x61, 0x6b, 0x12, 0x25, 0x0a, 0x0e, 0x77, 0x69, 0x74, 0x6e, 0x65, 0x73, 0x73, 0x5f, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x77, 0x69, - 0x74, 0x6e, 0x65, 0x73, 0x73, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x26, 0x0a, 0x06, 0x6f, - 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x73, 0x69, - 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x78, 0x4f, 0x75, 0x74, 0x52, 0x06, 0x6f, 0x75, 0x74, - 0x70, 0x75, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x69, 0x67, 0x68, 0x61, 0x73, 0x68, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x73, 0x69, 0x67, 0x68, 0x61, 0x73, 0x68, 0x12, 0x1f, 0x0a, - 0x0b, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x08, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x0a, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x2a, - 0x0a, 0x11, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x73, 0x70, - 0x65, 0x6e, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x74, 0x61, 0x70, 0x72, 0x6f, - 0x6f, 0x74, 0x4b, 0x65, 0x79, 0x53, 0x70, 0x65, 0x6e, 0x64, 0x22, 0x96, 0x01, 0x0a, 0x07, 0x53, - 0x69, 0x67, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x20, 0x0a, 0x0c, 0x72, 0x61, 0x77, 0x5f, 0x74, 0x78, - 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x72, 0x61, - 0x77, 0x54, 0x78, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x36, 0x0a, 0x0a, 0x73, 0x69, 0x67, 0x6e, - 0x5f, 0x64, 0x65, 0x73, 0x63, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, - 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x44, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x44, 0x65, 0x73, 0x63, 0x73, - 0x12, 0x31, 0x0a, 0x0c, 0x70, 0x72, 0x65, 0x76, 0x5f, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x54, 0x78, 0x4f, 0x75, 0x74, 0x52, 0x0b, 0x70, 0x72, 0x65, 0x76, 0x4f, 0x75, 0x74, 0x70, - 0x75, 0x74, 0x73, 0x22, 0x25, 0x0a, 0x08, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, - 0x19, 0x0a, 0x08, 0x72, 0x61, 0x77, 0x5f, 0x73, 0x69, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0c, 0x52, 0x07, 0x72, 0x61, 0x77, 0x53, 0x69, 0x67, 0x73, 0x22, 0x46, 0x0a, 0x0b, 0x49, 0x6e, - 0x70, 0x75, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x77, 0x69, 0x74, - 0x6e, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x77, 0x69, 0x74, 0x6e, - 0x65, 0x73, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x69, 0x67, 0x5f, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x53, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x22, 0x4c, 0x0a, 0x0f, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x39, 0x0a, 0x0d, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x73, - 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x52, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, - 0x22, 0x92, 0x01, 0x0a, 0x0e, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x03, 0x6d, 0x73, 0x67, 0x12, 0x2c, 0x0a, 0x07, 0x6b, 0x65, 0x79, 0x5f, 0x6c, 0x6f, 0x63, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x4b, 0x65, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x06, 0x6b, 0x65, 0x79, - 0x4c, 0x6f, 0x63, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x68, 0x61, - 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, - 0x48, 0x61, 0x73, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x5f, - 0x73, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x61, - 0x63, 0x74, 0x53, 0x69, 0x67, 0x22, 0x2f, 0x0a, 0x0f, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x5a, 0x0a, 0x10, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, + 0x77, 0x65, 0x61, 0x6b, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x61, 0x70, 0x5f, 0x74, 0x77, 0x65, 0x61, + 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x74, 0x61, 0x70, 0x54, 0x77, 0x65, 0x61, + 0x6b, 0x12, 0x25, 0x0a, 0x0e, 0x77, 0x69, 0x74, 0x6e, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x77, 0x69, 0x74, 0x6e, 0x65, + 0x73, 0x73, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x26, 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, + 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x54, 0x78, 0x4f, 0x75, 0x74, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, + 0x12, 0x18, 0x0a, 0x07, 0x73, 0x69, 0x67, 0x68, 0x61, 0x73, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x07, 0x73, 0x69, 0x67, 0x68, 0x61, 0x73, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, + 0x70, 0x75, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x0a, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x34, 0x0a, 0x0b, 0x73, + 0x69, 0x67, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x13, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x4d, + 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x0a, 0x73, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x74, 0x68, 0x6f, + 0x64, 0x22, 0x96, 0x01, 0x0a, 0x07, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x20, 0x0a, + 0x0c, 0x72, 0x61, 0x77, 0x5f, 0x74, 0x78, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x72, 0x61, 0x77, 0x54, 0x78, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, + 0x36, 0x0a, 0x0a, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, + 0x67, 0x6e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x44, 0x65, 0x73, 0x63, 0x73, 0x12, 0x31, 0x0a, 0x0c, 0x70, 0x72, 0x65, 0x76, 0x5f, + 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, + 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x78, 0x4f, 0x75, 0x74, 0x52, 0x0b, 0x70, + 0x72, 0x65, 0x76, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x22, 0x25, 0x0a, 0x08, 0x53, 0x69, + 0x67, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x61, 0x77, 0x5f, 0x73, 0x69, + 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x72, 0x61, 0x77, 0x53, 0x69, 0x67, + 0x73, 0x22, 0x46, 0x0a, 0x0b, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x12, 0x18, 0x0a, 0x07, 0x77, 0x69, 0x74, 0x6e, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0c, 0x52, 0x07, 0x77, 0x69, 0x74, 0x6e, 0x65, 0x73, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x69, + 0x67, 0x5f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, + 0x73, 0x69, 0x67, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0x4c, 0x0a, 0x0f, 0x49, 0x6e, 0x70, + 0x75, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x39, 0x0a, 0x0d, + 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, + 0x70, 0x75, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, + 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x22, 0x92, 0x01, 0x0a, 0x0e, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x73, - 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x12, 0x1c, 0x0a, 0x09, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, - 0x62, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, - 0x65, 0x79, 0x22, 0x29, 0x0a, 0x11, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x22, 0xa2, 0x01, - 0x0a, 0x10, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x65, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x5f, - 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x65, 0x70, - 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, - 0x07, 0x6b, 0x65, 0x79, 0x5f, 0x6c, 0x6f, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, - 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4b, 0x65, 0x79, 0x4c, 0x6f, 0x63, 0x61, - 0x74, 0x6f, 0x72, 0x42, 0x02, 0x18, 0x01, 0x52, 0x06, 0x6b, 0x65, 0x79, 0x4c, 0x6f, 0x63, 0x12, - 0x31, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x16, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4b, 0x65, 0x79, 0x44, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x44, 0x65, - 0x73, 0x63, 0x22, 0x32, 0x0a, 0x11, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x68, 0x61, 0x72, 0x65, - 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x68, 0x61, - 0x72, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x22, 0x3d, 0x0a, 0x09, 0x54, 0x77, 0x65, 0x61, 0x6b, 0x44, - 0x65, 0x73, 0x63, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x77, 0x65, 0x61, 0x6b, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x05, 0x74, 0x77, 0x65, 0x61, 0x6b, 0x12, 0x1a, 0x0a, 0x09, 0x69, 0x73, 0x5f, - 0x78, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, - 0x58, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x59, 0x0a, 0x10, 0x54, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, - 0x54, 0x77, 0x65, 0x61, 0x6b, 0x44, 0x65, 0x73, 0x63, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x6b, 0x65, - 0x79, 0x5f, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0c, 0x6b, 0x65, 0x79, 0x53, 0x70, 0x65, 0x6e, 0x64, 0x4f, 0x6e, 0x6c, 0x79, - 0x22, 0xb4, 0x01, 0x0a, 0x18, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, 0x6f, 0x6d, 0x62, 0x69, - 0x6e, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, - 0x12, 0x61, 0x6c, 0x6c, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6b, - 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x10, 0x61, 0x6c, 0x6c, 0x53, 0x69, - 0x67, 0x6e, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x73, 0x12, 0x2a, 0x0a, 0x06, 0x74, - 0x77, 0x65, 0x61, 0x6b, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x73, 0x69, - 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x77, 0x65, 0x61, 0x6b, 0x44, 0x65, 0x73, 0x63, 0x52, - 0x06, 0x74, 0x77, 0x65, 0x61, 0x6b, 0x73, 0x12, 0x3e, 0x0a, 0x0d, 0x74, 0x61, 0x70, 0x72, 0x6f, - 0x6f, 0x74, 0x5f, 0x74, 0x77, 0x65, 0x61, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, - 0x54, 0x77, 0x65, 0x61, 0x6b, 0x44, 0x65, 0x73, 0x63, 0x52, 0x0c, 0x74, 0x61, 0x70, 0x72, 0x6f, - 0x6f, 0x74, 0x54, 0x77, 0x65, 0x61, 0x6b, 0x22, 0x70, 0x0a, 0x19, 0x4d, 0x75, 0x53, 0x69, 0x67, - 0x32, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, - 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x62, - 0x69, 0x6e, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x14, 0x74, 0x61, 0x70, 0x72, 0x6f, - 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x6b, 0x65, 0x79, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x12, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x22, 0x9b, 0x02, 0x0a, 0x14, 0x4d, 0x75, - 0x53, 0x69, 0x67, 0x32, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x07, 0x6b, 0x65, 0x79, 0x5f, 0x6c, 0x6f, 0x63, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4b, 0x65, - 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x06, 0x6b, 0x65, 0x79, 0x4c, 0x6f, 0x63, - 0x12, 0x2c, 0x0a, 0x12, 0x61, 0x6c, 0x6c, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x5f, 0x70, - 0x75, 0x62, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x10, 0x61, 0x6c, - 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x73, 0x12, 0x3b, - 0x0a, 0x1a, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x5f, 0x70, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, - 0x28, 0x0c, 0x52, 0x17, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x50, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x06, 0x74, - 0x77, 0x65, 0x61, 0x6b, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x73, 0x69, - 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x77, 0x65, 0x61, 0x6b, 0x44, 0x65, 0x73, 0x63, 0x52, - 0x06, 0x74, 0x77, 0x65, 0x61, 0x6b, 0x73, 0x12, 0x3e, 0x0a, 0x0d, 0x74, 0x61, 0x70, 0x72, 0x6f, - 0x6f, 0x74, 0x5f, 0x74, 0x77, 0x65, 0x61, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, - 0x54, 0x77, 0x65, 0x61, 0x6b, 0x44, 0x65, 0x73, 0x63, 0x52, 0x0c, 0x74, 0x61, 0x70, 0x72, 0x6f, - 0x6f, 0x74, 0x54, 0x77, 0x65, 0x61, 0x6b, 0x22, 0xe3, 0x01, 0x0a, 0x15, 0x4d, 0x75, 0x53, 0x69, - 0x67, 0x32, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, - 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, - 0x4b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x14, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x12, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x12, 0x2e, 0x0a, 0x13, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x70, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x11, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4e, - 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x68, 0x61, 0x76, 0x65, 0x5f, 0x61, 0x6c, - 0x6c, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, - 0x68, 0x61, 0x76, 0x65, 0x41, 0x6c, 0x6c, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x22, 0x79, 0x0a, - 0x1b, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4e, - 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, + 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x12, 0x2c, 0x0a, 0x07, + 0x6b, 0x65, 0x79, 0x5f, 0x6c, 0x6f, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, + 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4b, 0x65, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x74, + 0x6f, 0x72, 0x52, 0x06, 0x6b, 0x65, 0x79, 0x4c, 0x6f, 0x63, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x6f, + 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0a, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x63, + 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x5f, 0x73, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x53, 0x69, 0x67, 0x22, 0x2f, 0x0a, 0x0f, + 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x12, + 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x5a, 0x0a, + 0x10, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, + 0x71, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, + 0x6d, 0x73, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x22, 0x29, 0x0a, 0x11, 0x56, 0x65, 0x72, + 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x12, 0x14, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x22, 0xa2, 0x01, 0x0a, 0x10, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, 0x4b, + 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x65, 0x70, 0x68, + 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x65, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x50, 0x75, + 0x62, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x07, 0x6b, 0x65, 0x79, 0x5f, 0x6c, 0x6f, 0x63, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x4b, 0x65, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x02, 0x18, 0x01, 0x52, 0x06, + 0x6b, 0x65, 0x79, 0x4c, 0x6f, 0x63, 0x12, 0x31, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x64, 0x65, + 0x73, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x4b, 0x65, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, + 0x52, 0x07, 0x6b, 0x65, 0x79, 0x44, 0x65, 0x73, 0x63, 0x22, 0x32, 0x0a, 0x11, 0x53, 0x68, 0x61, + 0x72, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, + 0x0a, 0x0a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x09, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x22, 0x3d, 0x0a, + 0x09, 0x54, 0x77, 0x65, 0x61, 0x6b, 0x44, 0x65, 0x73, 0x63, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x77, + 0x65, 0x61, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x74, 0x77, 0x65, 0x61, 0x6b, + 0x12, 0x1a, 0x0a, 0x09, 0x69, 0x73, 0x5f, 0x78, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x58, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x59, 0x0a, 0x10, + 0x54, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x54, 0x77, 0x65, 0x61, 0x6b, 0x44, 0x65, 0x73, 0x63, + 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x6f, 0x6f, + 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x6b, 0x65, 0x79, 0x5f, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x5f, 0x6f, + 0x6e, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6b, 0x65, 0x79, 0x53, 0x70, + 0x65, 0x6e, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0xb4, 0x01, 0x0a, 0x18, 0x4d, 0x75, 0x53, 0x69, + 0x67, 0x32, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x61, 0x6c, 0x6c, 0x5f, 0x73, 0x69, 0x67, 0x6e, + 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, + 0x52, 0x10, 0x61, 0x6c, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6b, 0x65, + 0x79, 0x73, 0x12, 0x2a, 0x0a, 0x06, 0x74, 0x77, 0x65, 0x61, 0x6b, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x77, 0x65, + 0x61, 0x6b, 0x44, 0x65, 0x73, 0x63, 0x52, 0x06, 0x74, 0x77, 0x65, 0x61, 0x6b, 0x73, 0x12, 0x3e, + 0x0a, 0x0d, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x74, 0x77, 0x65, 0x61, 0x6b, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x54, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x54, 0x77, 0x65, 0x61, 0x6b, 0x44, 0x65, 0x73, 0x63, + 0x52, 0x0c, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x54, 0x77, 0x65, 0x61, 0x6b, 0x22, 0x70, + 0x0a, 0x19, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x4b, + 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, + 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x12, 0x30, + 0x0a, 0x14, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x12, 0x74, 0x61, + 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, + 0x22, 0x9b, 0x02, 0x0a, 0x14, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x07, 0x6b, 0x65, 0x79, + 0x5f, 0x6c, 0x6f, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x69, 0x67, + 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4b, 0x65, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x52, + 0x06, 0x6b, 0x65, 0x79, 0x4c, 0x6f, 0x63, 0x12, 0x2c, 0x0a, 0x12, 0x61, 0x6c, 0x6c, 0x5f, 0x73, + 0x69, 0x67, 0x6e, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0c, 0x52, 0x10, 0x61, 0x6c, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x50, 0x75, + 0x62, 0x6b, 0x65, 0x79, 0x73, 0x12, 0x3b, 0x0a, 0x1a, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x73, + 0x69, 0x67, 0x6e, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6e, 0x6f, 0x6e, + 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x17, 0x6f, 0x74, 0x68, 0x65, 0x72, + 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4e, 0x6f, 0x6e, 0x63, + 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x06, 0x74, 0x77, 0x65, 0x61, 0x6b, 0x73, 0x18, 0x04, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x77, 0x65, + 0x61, 0x6b, 0x44, 0x65, 0x73, 0x63, 0x52, 0x06, 0x74, 0x77, 0x65, 0x61, 0x6b, 0x73, 0x12, 0x3e, + 0x0a, 0x0d, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x74, 0x77, 0x65, 0x61, 0x6b, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x54, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x54, 0x77, 0x65, 0x61, 0x6b, 0x44, 0x65, 0x73, 0x63, + 0x52, 0x0c, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x54, 0x77, 0x65, 0x61, 0x6b, 0x22, 0xe3, + 0x01, 0x0a, 0x15, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x62, 0x69, + 0x6e, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, + 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x14, 0x74, 0x61, + 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x6b, + 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x12, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x6f, + 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x12, 0x2e, 0x0a, 0x13, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6e, 0x6f, 0x6e, + 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x11, 0x6c, 0x6f, 0x63, 0x61, 0x6c, + 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0f, + 0x68, 0x61, 0x76, 0x65, 0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x68, 0x61, 0x76, 0x65, 0x41, 0x6c, 0x6c, 0x4e, 0x6f, + 0x6e, 0x63, 0x65, 0x73, 0x22, 0x79, 0x0a, 0x1b, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x52, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x49, 0x64, 0x12, 0x3b, 0x0a, 0x1a, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x67, 0x6e, + 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x17, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x53, 0x69, 0x67, + 0x6e, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x22, + 0x46, 0x0a, 0x1c, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, + 0x72, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x26, 0x0a, 0x0f, 0x68, 0x61, 0x76, 0x65, 0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x68, 0x61, 0x76, 0x65, 0x41, 0x6c, + 0x6c, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x22, 0x73, 0x0a, 0x11, 0x4d, 0x75, 0x53, 0x69, 0x67, + 0x32, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x3b, 0x0a, 0x1a, 0x6f, - 0x74, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6c, - 0x69, 0x63, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, - 0x17, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6c, - 0x69, 0x63, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x22, 0x46, 0x0a, 0x1c, 0x4d, 0x75, 0x53, 0x69, - 0x67, 0x32, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x68, 0x61, 0x76, 0x65, - 0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x0d, 0x68, 0x61, 0x76, 0x65, 0x41, 0x6c, 0x6c, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, - 0x22, 0x73, 0x0a, 0x11, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, + 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x44, 0x69, 0x67, 0x65, + 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x07, 0x63, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x22, 0x4c, 0x0a, 0x12, + 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x36, 0x0a, 0x17, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x72, 0x74, + 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x15, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, + 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x72, 0x0a, 0x17, 0x4d, 0x75, + 0x53, 0x69, 0x67, 0x32, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x53, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, - 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, - 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x63, 0x6c, - 0x65, 0x61, 0x6e, 0x75, 0x70, 0x22, 0x4c, 0x0a, 0x12, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x53, - 0x69, 0x67, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x17, 0x6c, - 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x15, 0x6c, 0x6f, - 0x63, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x22, 0x72, 0x0a, 0x17, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, 0x6f, 0x6d, - 0x62, 0x69, 0x6e, 0x65, 0x53, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, - 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x38, 0x0a, - 0x18, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, - 0x16, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x22, 0x73, 0x0a, 0x18, 0x4d, 0x75, 0x53, 0x69, 0x67, - 0x32, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x53, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x68, 0x61, 0x76, 0x65, 0x5f, 0x61, 0x6c, 0x6c, 0x5f, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x11, 0x68, 0x61, 0x76, 0x65, 0x41, 0x6c, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x66, 0x69, - 0x6e, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x35, 0x0a, 0x14, - 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x49, 0x64, 0x22, 0x17, 0x0a, 0x15, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, 0x6c, 0x65, - 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xdb, 0x06, 0x0a, - 0x06, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x12, 0x34, 0x0a, 0x0d, 0x53, 0x69, 0x67, 0x6e, 0x4f, - 0x75, 0x74, 0x70, 0x75, 0x74, 0x52, 0x61, 0x77, 0x12, 0x10, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x11, 0x2e, 0x73, 0x69, 0x67, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x40, 0x0a, - 0x12, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x12, 0x10, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, - 0x67, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x18, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x49, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, - 0x40, 0x0a, 0x0b, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x17, - 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x18, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x12, 0x46, 0x0a, 0x0d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x12, 0x19, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, - 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x1a, 0x2e, - 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x12, 0x48, 0x0a, 0x0f, 0x44, 0x65, 0x72, - 0x69, 0x76, 0x65, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x12, 0x19, 0x2e, 0x73, - 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, 0x4b, 0x65, 0x79, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x11, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, 0x6f, 0x6d, - 0x62, 0x69, 0x6e, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x21, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, - 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x73, 0x69, - 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, 0x6f, 0x6d, 0x62, - 0x69, 0x6e, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x54, 0x0a, 0x13, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x14, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x52, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x24, 0x2e, - 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x52, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x75, + 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x38, 0x0a, 0x18, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x70, 0x61, + 0x72, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x16, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x50, 0x61, 0x72, + 0x74, 0x69, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x22, 0x73, + 0x0a, 0x18, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x53, + 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x68, 0x61, + 0x76, 0x65, 0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x68, 0x61, 0x76, 0x65, 0x41, 0x6c, 0x6c, + 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x66, 0x69, + 0x6e, 0x61, 0x6c, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x22, 0x35, 0x0a, 0x14, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, 0x6c, 0x65, + 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x17, 0x0a, 0x15, 0x4d, 0x75, + 0x53, 0x69, 0x67, 0x32, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x2a, 0x9c, 0x01, 0x0a, 0x0a, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x74, 0x68, + 0x6f, 0x64, 0x12, 0x1a, 0x0a, 0x16, 0x53, 0x49, 0x47, 0x4e, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, + 0x44, 0x5f, 0x57, 0x49, 0x54, 0x4e, 0x45, 0x53, 0x53, 0x5f, 0x56, 0x30, 0x10, 0x00, 0x12, 0x29, + 0x0a, 0x25, 0x53, 0x49, 0x47, 0x4e, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x54, 0x41, + 0x50, 0x52, 0x4f, 0x4f, 0x54, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x53, 0x50, 0x45, 0x4e, 0x44, 0x5f, + 0x42, 0x49, 0x50, 0x30, 0x30, 0x38, 0x36, 0x10, 0x01, 0x12, 0x21, 0x0a, 0x1d, 0x53, 0x49, 0x47, + 0x4e, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x54, 0x41, 0x50, 0x52, 0x4f, 0x4f, 0x54, + 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x53, 0x50, 0x45, 0x4e, 0x44, 0x10, 0x02, 0x12, 0x24, 0x0a, 0x20, + 0x53, 0x49, 0x47, 0x4e, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x54, 0x41, 0x50, 0x52, + 0x4f, 0x4f, 0x54, 0x5f, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x53, 0x50, 0x45, 0x4e, 0x44, + 0x10, 0x03, 0x32, 0xdb, 0x06, 0x0a, 0x06, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x12, 0x34, 0x0a, + 0x0d, 0x53, 0x69, 0x67, 0x6e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x52, 0x61, 0x77, 0x12, 0x10, + 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x71, + 0x1a, 0x11, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x12, 0x40, 0x0a, 0x12, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x49, 0x6e, + 0x70, 0x75, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x10, 0x2e, 0x73, 0x69, 0x67, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x18, 0x2e, 0x73, 0x69, + 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x40, 0x0a, 0x0b, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x12, 0x17, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, + 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x18, 0x2e, + 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x12, 0x46, 0x0a, 0x0d, 0x56, 0x65, 0x72, 0x69, 0x66, + 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x19, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x52, 0x65, 0x71, 0x1a, 0x1a, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, + 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x12, + 0x48, 0x0a, 0x0f, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, 0x4b, + 0x65, 0x79, 0x12, 0x19, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x68, 0x61, + 0x72, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, + 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, 0x4b, 0x65, + 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x11, 0x4d, 0x75, 0x53, + 0x69, 0x67, 0x32, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x21, + 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, + 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x22, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x75, 0x53, 0x69, + 0x67, 0x32, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x13, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x2e, 0x73, + 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x53, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x73, 0x69, + 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x53, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x14, 0x4d, + 0x75, 0x53, 0x69, 0x67, 0x32, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x6e, + 0x63, 0x65, 0x73, 0x12, 0x24, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x6e, 0x63, - 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4d, 0x75, - 0x53, 0x69, 0x67, 0x32, 0x53, 0x69, 0x67, 0x6e, 0x12, 0x1a, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, - 0x75, 0x53, 0x69, 0x67, 0x32, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x57, 0x0a, 0x10, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, 0x6f, 0x6d, 0x62, 0x69, - 0x6e, 0x65, 0x53, 0x69, 0x67, 0x12, 0x20, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x53, 0x69, 0x67, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x53, - 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x4d, 0x75, - 0x53, 0x69, 0x67, 0x32, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x12, 0x1d, 0x2e, 0x73, 0x69, - 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, 0x6c, 0x65, 0x61, - 0x6e, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x73, 0x69, 0x67, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, 0x6c, 0x65, 0x61, 0x6e, - 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, - 0x6e, 0x67, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x6c, 0x6e, 0x64, 0x2f, 0x6c, 0x6e, - 0x72, 0x70, 0x63, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x73, 0x69, 0x67, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, + 0x65, 0x72, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x45, 0x0a, 0x0a, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x53, 0x69, 0x67, 0x6e, 0x12, 0x1a, + 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x53, + 0x69, 0x67, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x73, 0x69, 0x67, + 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x53, 0x69, 0x67, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x10, 0x4d, 0x75, 0x53, 0x69, 0x67, + 0x32, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x53, 0x69, 0x67, 0x12, 0x20, 0x2e, 0x73, 0x69, + 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, 0x6f, 0x6d, 0x62, + 0x69, 0x6e, 0x65, 0x53, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, + 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, 0x6f, + 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x53, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x4e, 0x0a, 0x0d, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, + 0x70, 0x12, 0x1d, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x75, 0x53, 0x69, + 0x67, 0x32, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1e, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x75, 0x53, 0x69, 0x67, + 0x32, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, + 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f, + 0x6c, 0x6e, 0x64, 0x2f, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, + 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2102,79 +2194,82 @@ func file_signrpc_signer_proto_rawDescGZIP() []byte { return file_signrpc_signer_proto_rawDescData } +var file_signrpc_signer_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_signrpc_signer_proto_msgTypes = make([]protoimpl.MessageInfo, 28) var file_signrpc_signer_proto_goTypes = []interface{}{ - (*KeyLocator)(nil), // 0: signrpc.KeyLocator - (*KeyDescriptor)(nil), // 1: signrpc.KeyDescriptor - (*TxOut)(nil), // 2: signrpc.TxOut - (*SignDescriptor)(nil), // 3: signrpc.SignDescriptor - (*SignReq)(nil), // 4: signrpc.SignReq - (*SignResp)(nil), // 5: signrpc.SignResp - (*InputScript)(nil), // 6: signrpc.InputScript - (*InputScriptResp)(nil), // 7: signrpc.InputScriptResp - (*SignMessageReq)(nil), // 8: signrpc.SignMessageReq - (*SignMessageResp)(nil), // 9: signrpc.SignMessageResp - (*VerifyMessageReq)(nil), // 10: signrpc.VerifyMessageReq - (*VerifyMessageResp)(nil), // 11: signrpc.VerifyMessageResp - (*SharedKeyRequest)(nil), // 12: signrpc.SharedKeyRequest - (*SharedKeyResponse)(nil), // 13: signrpc.SharedKeyResponse - (*TweakDesc)(nil), // 14: signrpc.TweakDesc - (*TaprootTweakDesc)(nil), // 15: signrpc.TaprootTweakDesc - (*MuSig2CombineKeysRequest)(nil), // 16: signrpc.MuSig2CombineKeysRequest - (*MuSig2CombineKeysResponse)(nil), // 17: signrpc.MuSig2CombineKeysResponse - (*MuSig2SessionRequest)(nil), // 18: signrpc.MuSig2SessionRequest - (*MuSig2SessionResponse)(nil), // 19: signrpc.MuSig2SessionResponse - (*MuSig2RegisterNoncesRequest)(nil), // 20: signrpc.MuSig2RegisterNoncesRequest - (*MuSig2RegisterNoncesResponse)(nil), // 21: signrpc.MuSig2RegisterNoncesResponse - (*MuSig2SignRequest)(nil), // 22: signrpc.MuSig2SignRequest - (*MuSig2SignResponse)(nil), // 23: signrpc.MuSig2SignResponse - (*MuSig2CombineSigRequest)(nil), // 24: signrpc.MuSig2CombineSigRequest - (*MuSig2CombineSigResponse)(nil), // 25: signrpc.MuSig2CombineSigResponse - (*MuSig2CleanupRequest)(nil), // 26: signrpc.MuSig2CleanupRequest - (*MuSig2CleanupResponse)(nil), // 27: signrpc.MuSig2CleanupResponse + (SignMethod)(0), // 0: signrpc.SignMethod + (*KeyLocator)(nil), // 1: signrpc.KeyLocator + (*KeyDescriptor)(nil), // 2: signrpc.KeyDescriptor + (*TxOut)(nil), // 3: signrpc.TxOut + (*SignDescriptor)(nil), // 4: signrpc.SignDescriptor + (*SignReq)(nil), // 5: signrpc.SignReq + (*SignResp)(nil), // 6: signrpc.SignResp + (*InputScript)(nil), // 7: signrpc.InputScript + (*InputScriptResp)(nil), // 8: signrpc.InputScriptResp + (*SignMessageReq)(nil), // 9: signrpc.SignMessageReq + (*SignMessageResp)(nil), // 10: signrpc.SignMessageResp + (*VerifyMessageReq)(nil), // 11: signrpc.VerifyMessageReq + (*VerifyMessageResp)(nil), // 12: signrpc.VerifyMessageResp + (*SharedKeyRequest)(nil), // 13: signrpc.SharedKeyRequest + (*SharedKeyResponse)(nil), // 14: signrpc.SharedKeyResponse + (*TweakDesc)(nil), // 15: signrpc.TweakDesc + (*TaprootTweakDesc)(nil), // 16: signrpc.TaprootTweakDesc + (*MuSig2CombineKeysRequest)(nil), // 17: signrpc.MuSig2CombineKeysRequest + (*MuSig2CombineKeysResponse)(nil), // 18: signrpc.MuSig2CombineKeysResponse + (*MuSig2SessionRequest)(nil), // 19: signrpc.MuSig2SessionRequest + (*MuSig2SessionResponse)(nil), // 20: signrpc.MuSig2SessionResponse + (*MuSig2RegisterNoncesRequest)(nil), // 21: signrpc.MuSig2RegisterNoncesRequest + (*MuSig2RegisterNoncesResponse)(nil), // 22: signrpc.MuSig2RegisterNoncesResponse + (*MuSig2SignRequest)(nil), // 23: signrpc.MuSig2SignRequest + (*MuSig2SignResponse)(nil), // 24: signrpc.MuSig2SignResponse + (*MuSig2CombineSigRequest)(nil), // 25: signrpc.MuSig2CombineSigRequest + (*MuSig2CombineSigResponse)(nil), // 26: signrpc.MuSig2CombineSigResponse + (*MuSig2CleanupRequest)(nil), // 27: signrpc.MuSig2CleanupRequest + (*MuSig2CleanupResponse)(nil), // 28: signrpc.MuSig2CleanupResponse } var file_signrpc_signer_proto_depIdxs = []int32{ - 0, // 0: signrpc.KeyDescriptor.key_loc:type_name -> signrpc.KeyLocator - 1, // 1: signrpc.SignDescriptor.key_desc:type_name -> signrpc.KeyDescriptor - 2, // 2: signrpc.SignDescriptor.output:type_name -> signrpc.TxOut - 3, // 3: signrpc.SignReq.sign_descs:type_name -> signrpc.SignDescriptor - 2, // 4: signrpc.SignReq.prev_outputs:type_name -> signrpc.TxOut - 6, // 5: signrpc.InputScriptResp.input_scripts:type_name -> signrpc.InputScript - 0, // 6: signrpc.SignMessageReq.key_loc:type_name -> signrpc.KeyLocator - 0, // 7: signrpc.SharedKeyRequest.key_loc:type_name -> signrpc.KeyLocator - 1, // 8: signrpc.SharedKeyRequest.key_desc:type_name -> signrpc.KeyDescriptor - 14, // 9: signrpc.MuSig2CombineKeysRequest.tweaks:type_name -> signrpc.TweakDesc - 15, // 10: signrpc.MuSig2CombineKeysRequest.taproot_tweak:type_name -> signrpc.TaprootTweakDesc - 0, // 11: signrpc.MuSig2SessionRequest.key_loc:type_name -> signrpc.KeyLocator - 14, // 12: signrpc.MuSig2SessionRequest.tweaks:type_name -> signrpc.TweakDesc - 15, // 13: signrpc.MuSig2SessionRequest.taproot_tweak:type_name -> signrpc.TaprootTweakDesc - 4, // 14: signrpc.Signer.SignOutputRaw:input_type -> signrpc.SignReq - 4, // 15: signrpc.Signer.ComputeInputScript:input_type -> signrpc.SignReq - 8, // 16: signrpc.Signer.SignMessage:input_type -> signrpc.SignMessageReq - 10, // 17: signrpc.Signer.VerifyMessage:input_type -> signrpc.VerifyMessageReq - 12, // 18: signrpc.Signer.DeriveSharedKey:input_type -> signrpc.SharedKeyRequest - 16, // 19: signrpc.Signer.MuSig2CombineKeys:input_type -> signrpc.MuSig2CombineKeysRequest - 18, // 20: signrpc.Signer.MuSig2CreateSession:input_type -> signrpc.MuSig2SessionRequest - 20, // 21: signrpc.Signer.MuSig2RegisterNonces:input_type -> signrpc.MuSig2RegisterNoncesRequest - 22, // 22: signrpc.Signer.MuSig2Sign:input_type -> signrpc.MuSig2SignRequest - 24, // 23: signrpc.Signer.MuSig2CombineSig:input_type -> signrpc.MuSig2CombineSigRequest - 26, // 24: signrpc.Signer.MuSig2Cleanup:input_type -> signrpc.MuSig2CleanupRequest - 5, // 25: signrpc.Signer.SignOutputRaw:output_type -> signrpc.SignResp - 7, // 26: signrpc.Signer.ComputeInputScript:output_type -> signrpc.InputScriptResp - 9, // 27: signrpc.Signer.SignMessage:output_type -> signrpc.SignMessageResp - 11, // 28: signrpc.Signer.VerifyMessage:output_type -> signrpc.VerifyMessageResp - 13, // 29: signrpc.Signer.DeriveSharedKey:output_type -> signrpc.SharedKeyResponse - 17, // 30: signrpc.Signer.MuSig2CombineKeys:output_type -> signrpc.MuSig2CombineKeysResponse - 19, // 31: signrpc.Signer.MuSig2CreateSession:output_type -> signrpc.MuSig2SessionResponse - 21, // 32: signrpc.Signer.MuSig2RegisterNonces:output_type -> signrpc.MuSig2RegisterNoncesResponse - 23, // 33: signrpc.Signer.MuSig2Sign:output_type -> signrpc.MuSig2SignResponse - 25, // 34: signrpc.Signer.MuSig2CombineSig:output_type -> signrpc.MuSig2CombineSigResponse - 27, // 35: signrpc.Signer.MuSig2Cleanup:output_type -> signrpc.MuSig2CleanupResponse - 25, // [25:36] is the sub-list for method output_type - 14, // [14:25] is the sub-list for method input_type - 14, // [14:14] is the sub-list for extension type_name - 14, // [14:14] is the sub-list for extension extendee - 0, // [0:14] is the sub-list for field type_name + 1, // 0: signrpc.KeyDescriptor.key_loc:type_name -> signrpc.KeyLocator + 2, // 1: signrpc.SignDescriptor.key_desc:type_name -> signrpc.KeyDescriptor + 3, // 2: signrpc.SignDescriptor.output:type_name -> signrpc.TxOut + 0, // 3: signrpc.SignDescriptor.sign_method:type_name -> signrpc.SignMethod + 4, // 4: signrpc.SignReq.sign_descs:type_name -> signrpc.SignDescriptor + 3, // 5: signrpc.SignReq.prev_outputs:type_name -> signrpc.TxOut + 7, // 6: signrpc.InputScriptResp.input_scripts:type_name -> signrpc.InputScript + 1, // 7: signrpc.SignMessageReq.key_loc:type_name -> signrpc.KeyLocator + 1, // 8: signrpc.SharedKeyRequest.key_loc:type_name -> signrpc.KeyLocator + 2, // 9: signrpc.SharedKeyRequest.key_desc:type_name -> signrpc.KeyDescriptor + 15, // 10: signrpc.MuSig2CombineKeysRequest.tweaks:type_name -> signrpc.TweakDesc + 16, // 11: signrpc.MuSig2CombineKeysRequest.taproot_tweak:type_name -> signrpc.TaprootTweakDesc + 1, // 12: signrpc.MuSig2SessionRequest.key_loc:type_name -> signrpc.KeyLocator + 15, // 13: signrpc.MuSig2SessionRequest.tweaks:type_name -> signrpc.TweakDesc + 16, // 14: signrpc.MuSig2SessionRequest.taproot_tweak:type_name -> signrpc.TaprootTweakDesc + 5, // 15: signrpc.Signer.SignOutputRaw:input_type -> signrpc.SignReq + 5, // 16: signrpc.Signer.ComputeInputScript:input_type -> signrpc.SignReq + 9, // 17: signrpc.Signer.SignMessage:input_type -> signrpc.SignMessageReq + 11, // 18: signrpc.Signer.VerifyMessage:input_type -> signrpc.VerifyMessageReq + 13, // 19: signrpc.Signer.DeriveSharedKey:input_type -> signrpc.SharedKeyRequest + 17, // 20: signrpc.Signer.MuSig2CombineKeys:input_type -> signrpc.MuSig2CombineKeysRequest + 19, // 21: signrpc.Signer.MuSig2CreateSession:input_type -> signrpc.MuSig2SessionRequest + 21, // 22: signrpc.Signer.MuSig2RegisterNonces:input_type -> signrpc.MuSig2RegisterNoncesRequest + 23, // 23: signrpc.Signer.MuSig2Sign:input_type -> signrpc.MuSig2SignRequest + 25, // 24: signrpc.Signer.MuSig2CombineSig:input_type -> signrpc.MuSig2CombineSigRequest + 27, // 25: signrpc.Signer.MuSig2Cleanup:input_type -> signrpc.MuSig2CleanupRequest + 6, // 26: signrpc.Signer.SignOutputRaw:output_type -> signrpc.SignResp + 8, // 27: signrpc.Signer.ComputeInputScript:output_type -> signrpc.InputScriptResp + 10, // 28: signrpc.Signer.SignMessage:output_type -> signrpc.SignMessageResp + 12, // 29: signrpc.Signer.VerifyMessage:output_type -> signrpc.VerifyMessageResp + 14, // 30: signrpc.Signer.DeriveSharedKey:output_type -> signrpc.SharedKeyResponse + 18, // 31: signrpc.Signer.MuSig2CombineKeys:output_type -> signrpc.MuSig2CombineKeysResponse + 20, // 32: signrpc.Signer.MuSig2CreateSession:output_type -> signrpc.MuSig2SessionResponse + 22, // 33: signrpc.Signer.MuSig2RegisterNonces:output_type -> signrpc.MuSig2RegisterNoncesResponse + 24, // 34: signrpc.Signer.MuSig2Sign:output_type -> signrpc.MuSig2SignResponse + 26, // 35: signrpc.Signer.MuSig2CombineSig:output_type -> signrpc.MuSig2CombineSigResponse + 28, // 36: signrpc.Signer.MuSig2Cleanup:output_type -> signrpc.MuSig2CleanupResponse + 26, // [26:37] is the sub-list for method output_type + 15, // [15:26] is the sub-list for method input_type + 15, // [15:15] is the sub-list for extension type_name + 15, // [15:15] is the sub-list for extension extendee + 0, // [0:15] is the sub-list for field type_name } func init() { file_signrpc_signer_proto_init() } @@ -2525,13 +2620,14 @@ func file_signrpc_signer_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_signrpc_signer_proto_rawDesc, - NumEnums: 0, + NumEnums: 1, NumMessages: 28, NumExtensions: 0, NumServices: 1, }, GoTypes: file_signrpc_signer_proto_goTypes, DependencyIndexes: file_signrpc_signer_proto_depIdxs, + EnumInfos: file_signrpc_signer_proto_enumTypes, MessageInfos: file_signrpc_signer_proto_msgTypes, }.Build() File_signrpc_signer_proto = out.File diff --git a/lnrpc/signrpc/signer.proto b/lnrpc/signrpc/signer.proto index 8b56e4a18..9085c6f67 100644 --- a/lnrpc/signrpc/signer.proto +++ b/lnrpc/signrpc/signer.proto @@ -175,6 +175,32 @@ message TxOut { bytes pk_script = 2; } +enum SignMethod { + /* + Specifies that a SegWit v0 (p2wkh, np2wkh, p2wsh) input script should be + signed. + */ + SIGN_METHOD_WITNESS_V0 = 0; + + /* + Specifies that a SegWit v1 (p2tr) input should be signed by using the + BIP0086 method (commit to internal key only). + */ + SIGN_METHOD_TAPROOT_KEY_SPEND_BIP0086 = 1; + + /* + Specifies that a SegWit v1 (p2tr) input should be signed by using a given + taproot hash to commit to in addition to the internal key. + */ + SIGN_METHOD_TAPROOT_KEY_SPEND = 2; + + /* + Specifies that a SegWit v1 (p2tr) input should be spent using the script + path and that a specific leaf script should be signed for. + */ + SIGN_METHOD_TAPROOT_SCRIPT_SPEND = 3; +} + message SignDescriptor { /* A descriptor that precisely describes *which* key to use for signing. This @@ -209,12 +235,23 @@ message SignDescriptor { */ bytes double_tweak = 3; + /* + The 32 byte input to the taproot tweak derivation that is used to derive + the output key from an internal key: outputKey = internalKey + + tagged_hash("tapTweak", internalKey || tapTweak). + + When doing a BIP 86 spend, this field can be an empty byte slice. + + When doing a normal key path spend, with the output key committing to an + actual script root, then this field should be: the tapscript root hash. + */ + bytes tap_tweak = 10; + /* The full script required to properly redeem the output. This field will - only be populated if a p2tr, p2wsh or a p2sh output is being signed. In case - taproot_key_spend is set to true then this value must correspond to the - taproot root hash (in case of a tapscript output) or the tap hashed internal - public key (in case of a BIP-0086 output). + only be populated if a p2tr, p2wsh or a p2sh output is being signed. If a + taproot script path spend is being attempted, then this should be the raw + leaf script. */ bytes witness_script = 4; @@ -236,12 +273,12 @@ message SignDescriptor { int32 input_index = 8; /* - Indicates that this should produce a signature that can be used for the key - spend path of a taproot input. This requires the witness_script field to be - set to the taproot root hash (in case of a tapscript output) or the tap - hashed internal public key (in case of a BIP-0086 output). + The sign method specifies how the input should be signed. Depending on the + method, either the tap_tweak, witness_script or both need to be specified. + Defaults to SegWit v0 signing to be backward compatible with older RPC + clients. */ - bool taproot_key_spend = 9; + SignMethod sign_method = 9; } message SignReq { diff --git a/lnrpc/signrpc/signer.swagger.json b/lnrpc/signrpc/signer.swagger.json index 6041beddc..edd0afa2e 100644 --- a/lnrpc/signrpc/signer.swagger.json +++ b/lnrpc/signrpc/signer.swagger.json @@ -731,10 +731,15 @@ "format": "byte", "description": "A private key that will be used in combination with its corresponding\nprivate key to derive the private key that is to be used to sign the target\ninput. Within the Lightning protocol, this value is typically the\ncommitment secret from a previously revoked commitment transaction. This\nvalue is in combination with two hash values, and the original private key\nto derive the private key to be used when signing.\n\nk = (privKey*sha256(pubKey || tweakPub) +\ntweakPriv*sha256(tweakPub || pubKey)) mod N" }, + "tap_tweak": { + "type": "string", + "format": "byte", + "description": "The 32 byte input to the taproot tweak derivation that is used to derive\nthe output key from an internal key: outputKey = internalKey +\ntagged_hash(\"tapTweak\", internalKey || tapTweak).\n\nWhen doing a BIP 86 spend, this field can be an empty byte slice.\n\nWhen doing a normal key path spend, with the output key committing to an\nactual script root, then this field should be: the tapscript root hash." + }, "witness_script": { "type": "string", "format": "byte", - "description": "The full script required to properly redeem the output. This field will\nonly be populated if a p2tr, p2wsh or a p2sh output is being signed. In case\ntaproot_key_spend is set to true then this value must correspond to the\ntaproot root hash (in case of a tapscript output) or the tap hashed internal\npublic key (in case of a BIP-0086 output)." + "description": "The full script required to properly redeem the output. This field will\nonly be populated if a p2tr, p2wsh or a p2sh output is being signed. If a\ntaproot script path spend is being attempted, then this should be the raw\nleaf script." }, "output": { "$ref": "#/definitions/signrpcTxOut", @@ -750,9 +755,9 @@ "format": "int32", "description": "The target input within the transaction that should be signed." }, - "taproot_key_spend": { - "type": "boolean", - "description": "Indicates that this should produce a signature that can be used for the key\nspend path of a taproot input. This requires the witness_script field to be\nset to the taproot root hash (in case of a tapscript output) or the tap\nhashed internal public key (in case of a BIP-0086 output)." + "sign_method": { + "$ref": "#/definitions/signrpcSignMethod", + "description": "The sign method specifies how the input should be signed. Depending on the\nmethod, either the tap_tweak, witness_script or both need to be specified.\nDefaults to SegWit v0 signing to be backward compatible with older RPC\nclients." } } }, @@ -788,6 +793,17 @@ } } }, + "signrpcSignMethod": { + "type": "string", + "enum": [ + "SIGN_METHOD_WITNESS_V0", + "SIGN_METHOD_TAPROOT_KEY_SPEND_BIP0086", + "SIGN_METHOD_TAPROOT_KEY_SPEND", + "SIGN_METHOD_TAPROOT_SCRIPT_SPEND" + ], + "default": "SIGN_METHOD_WITNESS_V0", + "description": " - SIGN_METHOD_WITNESS_V0: Specifies that a SegWit v0 (p2wkh, np2wkh, p2wsh) input script should be\nsigned.\n - SIGN_METHOD_TAPROOT_KEY_SPEND_BIP0086: Specifies that a SegWit v1 (p2tr) input should be signed by using the\nBIP0086 method (commit to internal key only).\n - SIGN_METHOD_TAPROOT_KEY_SPEND: Specifies that a SegWit v1 (p2tr) input should be signed by using a given\ntaproot hash to commit to in addition to the internal key.\n - SIGN_METHOD_TAPROOT_SCRIPT_SPEND: Specifies that a SegWit v1 (p2tr) input should be spent using the script\npath and that a specific leaf script should be signed for." + }, "signrpcSignReq": { "type": "object", "properties": { diff --git a/lnrpc/signrpc/signer_server.go b/lnrpc/signrpc/signer_server.go index 36a9de6fa..7dbdece22 100644 --- a/lnrpc/signrpc/signer_server.go +++ b/lnrpc/signrpc/signer_server.go @@ -361,16 +361,56 @@ func (s *Server) SignOutputRaw(_ context.Context, in *SignReq) (*SignResp, } } - // If a witness script isn't passed, then we can't proceed, as - // in the p2wsh case, we can't properly generate the sighash. - // A P2WKH doesn't need a witness script. But SignOutputRaw - // still needs to know the PK script that was used for the - // output. We'll send it in the WitnessScript field, the - // SignOutputRaw RPC will know what to do with it when creating - // the sighash. - if len(signDesc.WitnessScript) == 0 && !signDesc.TaprootKeySpend { - return nil, fmt.Errorf("witness script MUST be " + - "specified for non-taproot-key-spends") + // Check what sign method was selected by the user so, we know + // exactly what we're expecting and can prevent some of the more + // obvious usage errors. + signMethod, err := UnmarshalSignMethod(signDesc.SignMethod) + if err != nil { + return nil, fmt.Errorf("unable to unmarshal sign "+ + "method: %v", err) + } + if !signMethod.PkScriptCompatible(signDesc.Output.PkScript) { + return nil, fmt.Errorf("selected sign method %v is "+ + "not compatible with given pk script %x", + signMethod, signDesc.Output.PkScript) + } + + // Perform input validation according to the sign method. Not + // all methods require the same fields to be provided. + switch signMethod { + case input.WitnessV0SignMethod: + // If a witness script isn't passed, then we can't + // proceed, as in the p2wsh case, we can't properly + // generate the sighash. A P2WKH doesn't need a witness + // script. But SignOutputRaw still needs to know the PK + // script that was used for the output. We'll send it in + // the WitnessScript field, the SignOutputRaw RPC will + // know what to do with it when creating the sighash. + if len(signDesc.WitnessScript) == 0 { + return nil, fmt.Errorf("witness script MUST " + + "be specified for segwit v0 sign " + + "method") + } + + case input.TaprootKeySpendBIP0086SignMethod: + if len(signDesc.TapTweak) > 0 { + return nil, fmt.Errorf("tap tweak must be " + + "empty for BIP0086 key spend") + } + + case input.TaprootKeySpendSignMethod: + if len(signDesc.TapTweak) != sha256.Size { + return nil, fmt.Errorf("tap tweak must be " + + "specified for key spend with root " + + "hash") + } + + case input.TaprootScriptSpendSignMethod: + if len(signDesc.WitnessScript) == 0 { + return nil, fmt.Errorf("witness script MUST " + + "be specified for taproot script " + + "spend method") + } } // If the users provided a double tweak, then we'll need to @@ -390,10 +430,11 @@ func (s *Server) SignOutputRaw(_ context.Context, in *SignReq) (*SignResp, KeyLocator: keyLoc, PubKey: targetPubKey, }, - SingleTweak: signDesc.SingleTweak, - DoubleTweak: tweakPrivKey, - WitnessScript: signDesc.WitnessScript, - TaprootKeySpend: signDesc.TaprootKeySpend, + SingleTweak: signDesc.SingleTweak, + DoubleTweak: tweakPrivKey, + TapTweak: signDesc.TapTweak, + WitnessScript: signDesc.WitnessScript, + SignMethod: signMethod, Output: &wire.TxOut{ Value: signDesc.Output.Value, PkScript: signDesc.Output.PkScript, @@ -1097,3 +1138,24 @@ func UnmarshalTweaks(rpcTweaks []*TweakDesc, return tweaks, nil } + +// UnmarshalSignMethod parses the RPC sign method into the native counterpart. +func UnmarshalSignMethod(rpcSignMethod SignMethod) (input.SignMethod, error) { + switch rpcSignMethod { + case SignMethod_SIGN_METHOD_WITNESS_V0: + return input.WitnessV0SignMethod, nil + + case SignMethod_SIGN_METHOD_TAPROOT_KEY_SPEND_BIP0086: + return input.TaprootKeySpendBIP0086SignMethod, nil + + case SignMethod_SIGN_METHOD_TAPROOT_KEY_SPEND: + return input.TaprootKeySpendSignMethod, nil + + case SignMethod_SIGN_METHOD_TAPROOT_SCRIPT_SPEND: + return input.TaprootScriptSpendSignMethod, nil + + default: + return 0, fmt.Errorf("unknown RPC sign method <%d>", + rpcSignMethod) + } +} diff --git a/lntest/itest/lnd_taproot_test.go b/lntest/itest/lnd_taproot_test.go index 4492bf973..1d28248d0 100644 --- a/lntest/itest/lnd_taproot_test.go +++ b/lntest/itest/lnd_taproot_test.go @@ -26,6 +26,9 @@ import ( const ( testTaprootKeyFamily = 77 testAmount = 800_000 + signMethodBip86 = signrpc.SignMethod_SIGN_METHOD_TAPROOT_KEY_SPEND_BIP0086 + signMethodRootHash = signrpc.SignMethod_SIGN_METHOD_TAPROOT_KEY_SPEND + signMethodTapscript = signrpc.SignMethod_SIGN_METHOD_TAPROOT_SCRIPT_SPEND ) var ( @@ -193,6 +196,7 @@ func testTaprootSignOutputRawScriptSpend(ctxt context.Context, t *harnessTest, KeyDesc: keyDesc, Sighash: uint32(txscript.SigHashDefault), WitnessScript: leaf2.Script, + SignMethod: signMethodTapscript, }}, }, ) @@ -202,6 +206,27 @@ func testTaprootSignOutputRawScriptSpend(ctxt context.Context, t *harnessTest, "input 0 is missing its previous outpoint information", ) + // We also want to make sure we get an error when we don't specify the + // correct signing method. + _, err = alice.SignerClient.SignOutputRaw( + ctxt, &signrpc.SignReq{ + RawTxBytes: buf.Bytes(), + SignDescs: []*signrpc.SignDescriptor{{ + Output: utxoInfo[0], + InputIndex: 0, + KeyDesc: keyDesc, + Sighash: uint32(txscript.SigHashDefault), + WitnessScript: leaf2.Script, + }}, + PrevOutputs: utxoInfo, + }, + ) + require.Error(t.t, err) + require.Contains( + t.t, err.Error(), "selected sign method witness_v0 is not "+ + "compatible with given pk script 5120", + ) + // Do the actual signing now. signResp, err := alice.SignerClient.SignOutputRaw( ctxt, &signrpc.SignReq{ @@ -212,6 +237,7 @@ func testTaprootSignOutputRawScriptSpend(ctxt context.Context, t *harnessTest, KeyDesc: keyDesc, Sighash: uint32(txscript.SigHashDefault), WitnessScript: leaf2.Script, + SignMethod: signMethodTapscript, }}, PrevOutputs: utxoInfo, }, @@ -307,12 +333,12 @@ func testTaprootSignOutputRawKeySpendBip86(ctxt context.Context, ctxt, &signrpc.SignReq{ RawTxBytes: buf.Bytes(), SignDescs: []*signrpc.SignDescriptor{{ - Output: utxoInfo[0], - InputIndex: 0, - KeyDesc: keyDesc, - SingleTweak: dummyKeyTweak[:], - Sighash: uint32(txscript.SigHashDefault), - TaprootKeySpend: true, + Output: utxoInfo[0], + InputIndex: 0, + KeyDesc: keyDesc, + SingleTweak: dummyKeyTweak[:], + Sighash: uint32(txscript.SigHashDefault), + SignMethod: signMethodBip86, }}, PrevOutputs: utxoInfo, }, @@ -405,13 +431,13 @@ func testTaprootSignOutputRawKeySpendRootHash(ctxt context.Context, ctxt, &signrpc.SignReq{ RawTxBytes: buf.Bytes(), SignDescs: []*signrpc.SignDescriptor{{ - Output: utxoInfo[0], - InputIndex: 0, - KeyDesc: keyDesc, - SingleTweak: dummyKeyTweak[:], - Sighash: uint32(txscript.SigHashDefault), - WitnessScript: rootHash[:], - TaprootKeySpend: true, + Output: utxoInfo[0], + InputIndex: 0, + KeyDesc: keyDesc, + SingleTweak: dummyKeyTweak[:], + Sighash: uint32(txscript.SigHashDefault), + TapTweak: rootHash[:], + SignMethod: signMethodRootHash, }}, PrevOutputs: utxoInfo, }, diff --git a/lnwallet/btcwallet/signer.go b/lnwallet/btcwallet/signer.go index 6b571ea1c..91ee53e80 100644 --- a/lnwallet/btcwallet/signer.go +++ b/lnwallet/btcwallet/signer.go @@ -372,21 +372,23 @@ func (b *BtcWallet) SignOutputRaw(tx *wire.MsgTx, // slightly different, so we need to account for that to get the // raw signature. var rawSig []byte - if signDesc.TaprootKeySpend { + switch signDesc.SignMethod { + case input.TaprootKeySpendBIP0086SignMethod, + input.TaprootKeySpendSignMethod: + // This function tweaks the private key using the tap - // root key supplied as the tweak. So we pass in the - // original private key to avoid it being double - // tweaked! + // root key supplied as the tweak. rawSig, err = txscript.RawTxInTaprootSignature( tx, sigHashes, signDesc.InputIndex, signDesc.Output.Value, signDesc.Output.PkScript, - signDesc.WitnessScript, signDesc.HashType, + signDesc.TapTweak, signDesc.HashType, privKey, ) if err != nil { return nil, err } - } else { + + case input.TaprootScriptSpendSignMethod: leaf := txscript.TapLeaf{ LeafVersion: txscript.BaseLeafVersion, Script: witnessScript, From 0e098ed9da1fcf150f02a848939b7e920a9ca3de Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 27 Apr 2022 21:05:43 +0200 Subject: [PATCH 04/13] mod: update to btcd/btcutil/psbt v1.1.4 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5d72ce803..7773e4eb8 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/btcsuite/btcd v0.22.0-beta.0.20220413172512-bf64c8bdbbbf github.com/btcsuite/btcd/btcec/v2 v2.2.0 github.com/btcsuite/btcd/btcutil v1.1.1 - github.com/btcsuite/btcd/btcutil/psbt v1.1.3 + github.com/btcsuite/btcd/btcutil/psbt v1.1.4 github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/btcsuite/btcwallet v0.15.0 diff --git a/go.sum b/go.sum index 445799fe7..d1989dbd2 100644 --- a/go.sum +++ b/go.sum @@ -87,8 +87,8 @@ github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUB github.com/btcsuite/btcd/btcutil v1.1.1 h1:hDcDaXiP0uEzR8Biqo2weECKqEw0uHDZ9ixIWevVQqY= github.com/btcsuite/btcd/btcutil v1.1.1/go.mod h1:nbKlBMNm9FGsdvKvu0essceubPiAcI57pYBNnsLAa34= github.com/btcsuite/btcd/btcutil/psbt v1.1.1/go.mod h1:KsGzRAzAdEimzgERpK9Xm+RhuCMvc4j2ctK0BEQ8JV0= -github.com/btcsuite/btcd/btcutil/psbt v1.1.3 h1:fMVX0CHlVkI3VSkwMZTArfdVUkfzLuJA+ElQTfqekOU= -github.com/btcsuite/btcd/btcutil/psbt v1.1.3/go.mod h1:GMJ40RHh0brZmhAKjltvYjakbVg9wQqfH+hZF96jIRE= +github.com/btcsuite/btcd/btcutil/psbt v1.1.4 h1:Edx4AfBn+YPam2KP5AobDitulGp4r1Oibm8oruzkMdI= +github.com/btcsuite/btcd/btcutil/psbt v1.1.4/go.mod h1:9AyU6EQVJ9Iw9zPyNT1lcdHd6cnEZdno5wLu5FY74os= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= From e4aa32fdf73c49db8a150ace996b0d193f286059 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 27 Apr 2022 21:05:44 +0200 Subject: [PATCH 05/13] btcwallet: prepare for supporting new signing methods --- lnwallet/btcwallet/psbt.go | 112 +++++++++++++++++++++++++++---------- 1 file changed, 81 insertions(+), 31 deletions(-) diff --git a/lnwallet/btcwallet/psbt.go b/lnwallet/btcwallet/psbt.go index ca19e1325..0ffa0c8af 100644 --- a/lnwallet/btcwallet/psbt.go +++ b/lnwallet/btcwallet/psbt.go @@ -8,6 +8,7 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil/psbt" "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcwallet/waddrmgr" "github.com/btcsuite/btcwallet/wallet" "github.com/lightningnetwork/lnd/input" @@ -111,7 +112,7 @@ func (b *BtcWallet) SignPsbt(packet *psbt.Packet) error { prevOutputFetcher := wallet.PsbtPrevOutputFetcher(packet) sigHashes := txscript.NewTxSigHashes(tx, prevOutputFetcher) for idx := range tx.TxIn { - in := packet.Inputs[idx] + in := &packet.Inputs[idx] // We can only sign if we have UTXO information available. Since // we don't finalize, we just skip over any input that we know @@ -165,47 +166,96 @@ func (b *BtcWallet) SignPsbt(packet *psbt.Packet) error { // Do we need to tweak anything? Single or double tweaks are // sent as custom/proprietary fields in the PSBT input section. privKey = maybeTweakPrivKeyPsbt(in.Unknowns, privKey) - pubKeyBytes := privKey.PubKey().SerializeCompressed() - // Extract the correct witness and/or legacy scripts now, - // depending on the type of input we sign. The txscript package - // has the peculiar requirement that the PkScript of a P2PKH - // must be given as the witness script in order for it to arrive - // at the correct sighash. That's why we call it subScript here - // instead of witness script. - subScript, scriptSig, err := prepareScripts(in) + // What kind of signature is expected from us and do we have all + // information we need? + signMethod, err := validateSigningMethod(in) if err != nil { - // We derived the correct key so we _are_ expected to - // sign this. Not being able to sign at this point means - // there's something wrong. - return fmt.Errorf("error deriving script for input "+ - "%d: %v", idx, err) + return err } - // We have everything we need for signing the input now. - sig, err := txscript.RawTxInWitnessSignature( - tx, sigHashes, idx, in.WitnessUtxo.Value, subScript, - in.SighashType, privKey, - ) - if err != nil { - return fmt.Errorf("error signing input %d: %v", idx, - err) + switch signMethod { + // For p2wkh, np2wkh and p2wsh. + case input.WitnessV0SignMethod: + err = signSegWitV0(in, tx, sigHashes, idx, privKey) + + default: + err = fmt.Errorf("unsupported signing method for "+ + "PSBT signing: %v", signMethod) + } + if err != nil { + return err } - packet.Inputs[idx].FinalScriptSig = scriptSig - packet.Inputs[idx].PartialSigs = append( - packet.Inputs[idx].PartialSigs, &psbt.PartialSig{ - PubKey: pubKeyBytes, - Signature: sig, - }, - ) } return nil } -// prepareScripts returns the appropriate witness and/or legacy scripts, +// validateSigningMethod attempts to detect the signing method that is required +// to sign for the given PSBT input and makes sure all information is available +// to do so. +func validateSigningMethod(in *psbt.PInput) (input.SignMethod, error) { + script, err := txscript.ParsePkScript(in.WitnessUtxo.PkScript) + if err != nil { + return 0, fmt.Errorf("error detecting signing method, "+ + "couldn't parse pkScript: %v", err) + } + + switch script.Class() { + case txscript.WitnessV0PubKeyHashTy, txscript.ScriptHashTy, + txscript.WitnessV0ScriptHashTy: + + return input.WitnessV0SignMethod, nil + + default: + return 0, fmt.Errorf("unsupported script class for signing "+ + "PSBT: %v", script.Class()) + } +} + +// SignSegWitV0 attempts to generate a signature for a SegWit version 0 input +// and stores it in the PartialSigs (and FinalScriptSig for np2wkh addresses) +// field. +func signSegWitV0(in *psbt.PInput, tx *wire.MsgTx, + sigHashes *txscript.TxSigHashes, idx int, + privKey *btcec.PrivateKey) error { + + pubKeyBytes := privKey.PubKey().SerializeCompressed() + + // Extract the correct witness and/or legacy scripts now, depending on + // the type of input we sign. The txscript package has the peculiar + // requirement that the PkScript of a P2PKH must be given as the witness + // script in order for it to arrive at the correct sighash. That's why + // we call it subScript here instead of witness script. + subScript, scriptSig, err := prepareScriptsV0(in) + if err != nil { + // We derived the correct key so we _are_ expected to sign this. + // Not being able to sign at this point means there's something + // wrong. + return fmt.Errorf("error deriving script for input %d: %v", idx, + err) + } + + // We have everything we need for signing the input now. + sig, err := txscript.RawTxInWitnessSignature( + tx, sigHashes, idx, in.WitnessUtxo.Value, subScript, + in.SighashType, privKey, + ) + if err != nil { + return fmt.Errorf("error signing input %d: %v", idx, err) + } + in.FinalScriptSig = scriptSig + in.PartialSigs = append(in.PartialSigs, &psbt.PartialSig{ + PubKey: pubKeyBytes, + Signature: sig, + }) + + return nil +} + +// prepareScriptsV0 returns the appropriate witness v0 and/or legacy scripts, // depending on the type of input that should be signed. -func prepareScripts(in psbt.PInput) ([]byte, []byte, error) { +func prepareScriptsV0(in *psbt.PInput) ([]byte, []byte, error) { switch { // It's a NP2WKH input: case len(in.RedeemScript) > 0: From 0f32a4456d29e8242d373b8dc5ad37431aaaed9d Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 27 Apr 2022 21:05:46 +0200 Subject: [PATCH 06/13] btcwallet: support taproot key spend signing in PSBT --- lnwallet/btcwallet/psbt.go | 90 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/lnwallet/btcwallet/psbt.go b/lnwallet/btcwallet/psbt.go index 0ffa0c8af..a45f640f3 100644 --- a/lnwallet/btcwallet/psbt.go +++ b/lnwallet/btcwallet/psbt.go @@ -2,6 +2,7 @@ package btcwallet import ( "bytes" + "crypto/sha256" "fmt" "github.com/btcsuite/btcd/btcec/v2" @@ -179,6 +180,20 @@ func (b *BtcWallet) SignPsbt(packet *psbt.Packet) error { case input.WitnessV0SignMethod: err = signSegWitV0(in, tx, sigHashes, idx, privKey) + // For p2tr BIP0086 key spend only. + case input.TaprootKeySpendBIP0086SignMethod: + rootHash := make([]byte, 0) + err = signSegWitV1KeySpend( + in, tx, sigHashes, idx, privKey, rootHash, + ) + + // For p2tr with script commitment key spend path. + case input.TaprootKeySpendSignMethod: + rootHash := in.TaprootMerkleRoot + err = signSegWitV1KeySpend( + in, tx, sigHashes, idx, privKey, rootHash, + ) + default: err = fmt.Errorf("unsupported signing method for "+ "PSBT signing: %v", signMethod) @@ -207,6 +222,60 @@ func validateSigningMethod(in *psbt.PInput) (input.SignMethod, error) { return input.WitnessV0SignMethod, nil + case txscript.WitnessV1TaprootTy: + if len(in.TaprootBip32Derivation) == 0 { + return 0, fmt.Errorf("cannot sign for taproot input " + + "without taproot BIP0032 derivation info") + } + + // Currently, we only support creating one signature per input. + // + // TODO(guggero): Should we support signing multiple paths at + // the same time? What are the performance and security + // implications? + if len(in.TaprootBip32Derivation) > 1 { + return 0, fmt.Errorf("unsupported multiple taproot " + + "BIP0032 derivation info found, can only " + + "sign for one at a time") + } + + derivation := in.TaprootBip32Derivation[0] + switch { + // No leaf hashes means this is the internal key we're signing + // with, so it's a key spend. And no merkle root means this is + // a BIP0086 output we're signing for. + case len(derivation.LeafHashes) == 0 && + len(in.TaprootMerkleRoot) == 0: + + return input.TaprootKeySpendBIP0086SignMethod, nil + + // A non-empty merkle root means we committed to a taproot hash + // that we need to use in the tap tweak. + case len(derivation.LeafHashes) == 0: + // Getting here means the merkle root isn't empty, but + // is it exactly the length we need? + if len(in.TaprootMerkleRoot) != sha256.Size { + return 0, fmt.Errorf("invalid taproot merkle "+ + "root length, got %d expected %d", + len(in.TaprootMerkleRoot), sha256.Size) + } + + return input.TaprootKeySpendSignMethod, nil + + // Currently, we only support signing for one leaf at a time. + // + // TODO(guggero): Should we support signing multiple paths at + // the same time? What are the performance and security + // implications? + case len(derivation.LeafHashes) == 1: + return input.TaprootScriptSpendSignMethod, nil + + default: + return 0, fmt.Errorf("unsupported number of leaf " + + "hashes in taproot BIP0032 derivation info, " + + "can only sign for one at a time") + } + default: return 0, fmt.Errorf("unsupported script class for signing "+ "PSBT: %v", script.Class()) @@ -253,6 +322,27 @@ func signSegWitV0(in *psbt.PInput, tx *wire.MsgTx, return nil } +// signSegWitV1KeySpend attempts to generate a signature for a SegWit version 1 +// (p2tr) input and stores it in the TaprootKeySpendSig field. +func signSegWitV1KeySpend(in *psbt.PInput, tx *wire.MsgTx, + sigHashes *txscript.TxSigHashes, idx int, privKey *btcec.PrivateKey, + tapscriptRootHash []byte) error { + + rawSig, err := txscript.RawTxInTaprootSignature( + tx, sigHashes, idx, in.WitnessUtxo.Value, + in.WitnessUtxo.PkScript, tapscriptRootHash, in.SighashType, + privKey, + ) + if err != nil { + return fmt.Errorf("error signing taproot input %d: %v", idx, + err) + } + + in.TaprootKeySpendSig = rawSig + + return nil +} + // prepareScriptsV0 returns the appropriate witness v0 and/or legacy scripts, // depending on the type of input that should be signed. func prepareScriptsV0(in *psbt.PInput) ([]byte, []byte, error) { From 35dd2d25eabf079d89b83e6766783ae10bb58b77 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 27 Apr 2022 21:05:47 +0200 Subject: [PATCH 07/13] btcwallet: support taproot script signing in PSBT --- lnwallet/btcwallet/psbt.go | 64 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/lnwallet/btcwallet/psbt.go b/lnwallet/btcwallet/psbt.go index a45f640f3..b621d6354 100644 --- a/lnwallet/btcwallet/psbt.go +++ b/lnwallet/btcwallet/psbt.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil/psbt" "github.com/btcsuite/btcd/txscript" @@ -194,6 +195,17 @@ func (b *BtcWallet) SignPsbt(packet *psbt.Packet) error { in, tx, sigHashes, idx, privKey, rootHash, ) + // For p2tr script spend path. + case input.TaprootScriptSpendSignMethod: + leafScript := in.TaprootLeafScript[0] + leaf := txscript.TapLeaf{ + LeafVersion: leafScript.LeafVersion, + Script: leafScript.Script, + } + err = signSegWitV1ScriptSpend( + in, tx, sigHashes, idx, privKey, leaf, + ) + default: err = fmt.Errorf("unsupported signing method for "+ "PSBT signing: %v", signMethod) @@ -268,6 +280,28 @@ func validateSigningMethod(in *psbt.PInput) (input.SignMethod, error) { // the same time? What are the performance and security // implications? case len(derivation.LeafHashes) == 1: + // If we're supposed to be signing for a leaf hash, we + // also expect the leaf script that hashes to that hash + // in the appropriate field. + if len(in.TaprootLeafScript) != 1 { + return 0, fmt.Errorf("specified leaf hash in " + + "taproot BIP0032 derivation but " + + "missing taproot leaf script") + } + + leafScript := in.TaprootLeafScript[0] + leaf := txscript.TapLeaf{ + LeafVersion: leafScript.LeafVersion, + Script: leafScript.Script, + } + leafHash := leaf.TapHash() + if !bytes.Equal(leafHash[:], derivation.LeafHashes[0]) { + return 0, fmt.Errorf("specified leaf hash in" + + "taproot BIP0032 derivation but " + + "corresponding taproot leaf script " + + "was not found") + } + return input.TaprootScriptSpendSignMethod, nil default: @@ -343,6 +377,36 @@ func signSegWitV1KeySpend(in *psbt.PInput, tx *wire.MsgTx, return nil } +// signSegWitV1ScriptSpend attempts to generate a signature for a SegWit version +// 1 (p2tr) input and stores it in the TaprootScriptSpendSig field. +func signSegWitV1ScriptSpend(in *psbt.PInput, tx *wire.MsgTx, + sigHashes *txscript.TxSigHashes, idx int, privKey *btcec.PrivateKey, + leaf txscript.TapLeaf) error { + + rawSig, err := txscript.RawTxInTapscriptSignature( + tx, sigHashes, idx, in.WitnessUtxo.Value, + in.WitnessUtxo.PkScript, leaf, in.SighashType, privKey, + ) + if err != nil { + return fmt.Errorf("error signing taproot script input %d: %v", + idx, err) + } + + leafHash := leaf.TapHash() + in.TaprootScriptSpendSig = append( + in.TaprootScriptSpendSig, &psbt.TaprootScriptSpendSig{ + XOnlyPubKey: in.TaprootBip32Derivation[0].XOnlyPubKey, + LeafHash: leafHash[:], + // We snip off the sighash flag from the end (if it was + // specified in the first place.) + Signature: rawSig[:schnorr.SignatureSize], + SigHash: in.SighashType, + }, + ) + + return nil +} + // prepareScriptsV0 returns the appropriate witness v0 and/or legacy scripts, // depending on the type of input that should be signed. func prepareScriptsV0(in *psbt.PInput) ([]byte, []byte, error) { From 7f4e977073b5ae7f27ee1313f6a2b7741b9ec7bf Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 27 Apr 2022 21:05:48 +0200 Subject: [PATCH 08/13] lntest+rpcwallet: support remote p2tr key spend signing --- lntest/itest/lnd_remote_signer_test.go | 16 ++-- lnwallet/rpcwallet/rpcwallet.go | 126 +++++++++++++++++++++---- 2 files changed, 113 insertions(+), 29 deletions(-) diff --git a/lntest/itest/lnd_remote_signer_test.go b/lntest/itest/lnd_remote_signer_test.go index e332a59ea..cda8fad47 100644 --- a/lntest/itest/lnd_remote_signer_test.go +++ b/lntest/itest/lnd_remote_signer_test.go @@ -125,16 +125,14 @@ func testRemoteSigner(net *lntest.NetworkHarness, t *harnessTest) { // TODO(guggero): Fix remote taproot signing by adding // the required fields to PSBT. - // testTaprootComputeInputScriptKeySpendBip86( - // ctxt, tt, wo, net, - // ) + testTaprootComputeInputScriptKeySpendBip86( + ctxt, tt, wo, net, + ) // testTaprootSignOutputRawScriptSpend(ctxt, tt, wo, net) - // testTaprootSignOutputRawKeySpendBip86( - // ctxt, tt, wo, net, - // ) - // testTaprootSignOutputRawKeySpendRootHash( - // ctxt, tt, wo, net, - // ) + testTaprootSignOutputRawKeySpendBip86(ctxt, tt, wo, net) + testTaprootSignOutputRawKeySpendRootHash( + ctxt, tt, wo, net, + ) testTaprootMuSig2KeySpendRootHash(ctxt, tt, wo, net) testTaprootMuSig2ScriptSpend(ctxt, tt, wo, net) testTaprootMuSig2KeySpendBip86(ctxt, tt, wo, net) diff --git a/lnwallet/rpcwallet/rpcwallet.go b/lnwallet/rpcwallet/rpcwallet.go index 4613b5223..d6d001d89 100644 --- a/lnwallet/rpcwallet/rpcwallet.go +++ b/lnwallet/rpcwallet/rpcwallet.go @@ -544,6 +544,35 @@ func (r *RPCKeyRing) ComputeInputScript(tx *wire.MsgTx, } signDesc.WitnessScript = witnessProgram + // If this is a p2tr address, then it must be a BIP0086 key spend if we + // are coming through this path (instead of SignOutputRaw). + switch addr.AddrType() { + case waddrmgr.TaprootPubKey: + signDesc.SignMethod = input.TaprootKeySpendBIP0086SignMethod + signDesc.WitnessScript = nil + + sig, err := r.remoteSign(tx, signDesc, sigScript) + if err != nil { + return nil, fmt.Errorf("error signing with remote"+ + "instance: %v", err) + } + + rawSig := sig.Serialize() + if signDesc.HashType != txscript.SigHashDefault { + rawSig = append(rawSig, byte(signDesc.HashType)) + } + + return &input.Script{ + Witness: wire.TxWitness{ + rawSig, + }, + }, nil + + case waddrmgr.TaprootScript: + return nil, fmt.Errorf("computing input script for taproot " + + "script address not supported") + } + // Let's give the TX to the remote instance now, so it can sign the // input. sig, err := r.remoteSign(tx, signDesc, sigScript) @@ -979,6 +1008,29 @@ func (r *RPCKeyRing) remoteSign(tx *wire.MsgTx, signDesc *input.SignDescriptor, }) } + // Add taproot specific fields. + switch signDesc.SignMethod { + case input.TaprootKeySpendBIP0086SignMethod, + input.TaprootKeySpendSignMethod: + + // The key identifying factor for a key spend is that we don't + // provide any leaf hashes to signal we want a signature for the + // key spend path (with the internal key). + d := in.Bip32Derivation[0] + in.TaprootBip32Derivation = []*psbt.TaprootBip32Derivation{{ + // The x-only public key is just our compressed public + // key without the first byte (type/parity). + XOnlyPubKey: d.PubKey[1:], + LeafHashes: nil, + MasterKeyFingerprint: d.MasterKeyFingerprint, + Bip32Path: d.Bip32Path, + }} + + // If this is a BIP0086 key spend then the tap tweak is empty, + // otherwise it's set to the Taproot root hash. + in.TaprootMerkleRoot = signDesc.TapTweak + } + // Okay, let's sign the input by the remote signer now. ctxt, cancel := context.WithTimeout(context.Background(), r.rpcTimeout) defer cancel() @@ -1009,28 +1061,62 @@ func (r *RPCKeyRing) remoteSign(tx *wire.MsgTx, signDesc *input.SignDescriptor, return nil, fmt.Errorf("remote signer returned invalid PSBT") } in = &signedPacket.Inputs[signDesc.InputIndex] - if len(in.PartialSigs) != 1 { - return nil, fmt.Errorf("remote signer returned invalid "+ - "partial signature, wanted 1, got %d", - len(in.PartialSigs)) - } - sigWithSigHash := in.PartialSigs[0] - if sigWithSigHash == nil { - return nil, fmt.Errorf("remote signer returned nil signature") - } - // The remote signer always adds the sighash type, so we need to account - // for that. - if len(sigWithSigHash.Signature) < ecdsa.MinSigLen+1 { - return nil, fmt.Errorf("remote signer returned invalid "+ - "partial signature: signature too short with %d bytes", - len(sigWithSigHash.Signature)) - } + return extractSignature(in, signDesc.SignMethod) +} - // Parse the signature, but chop off the last byte which is the sighash - // type. - sig := sigWithSigHash.Signature[0 : len(sigWithSigHash.Signature)-1] - return ecdsa.ParseDERSignature(sig) +// extractSignature attempts to extract the signature from the PSBT input, +// looking at different fields depending on the signing method that was used. +func extractSignature(in *psbt.PInput, + signMethod input.SignMethod) (input.Signature, error) { + + switch signMethod { + case input.WitnessV0SignMethod: + if len(in.PartialSigs) != 1 { + return nil, fmt.Errorf("remote signer returned "+ + "invalid partial signature, wanted 1, got %d", + len(in.PartialSigs)) + } + sigWithSigHash := in.PartialSigs[0] + if sigWithSigHash == nil { + return nil, fmt.Errorf("remote signer returned nil " + + "signature") + } + + // The remote signer always adds the sighash type, so we need to + // account for that. + sigLen := len(sigWithSigHash.Signature) + if sigLen < ecdsa.MinSigLen+1 { + return nil, fmt.Errorf("remote signer returned "+ + "invalid partial signature: signature too "+ + "short with %d bytes", sigLen) + } + + // Parse the signature, but chop off the last byte which is the + // sighash type. + sig := sigWithSigHash.Signature[0 : sigLen-1] + return ecdsa.ParseDERSignature(sig) + + // The type of key spend doesn't matter, the signature should be in the + // same field for both of those signing methods. + case input.TaprootKeySpendBIP0086SignMethod, + input.TaprootKeySpendSignMethod: + + sigLen := len(in.TaprootKeySpendSig) + if sigLen < schnorr.SignatureSize { + return nil, fmt.Errorf("remote signer returned "+ + "invalid key spend signature: signature too "+ + "short with %d bytes", sigLen) + } + + return schnorr.ParseSignature( + in.TaprootKeySpendSig[:schnorr.SignatureSize], + ) + + default: + return nil, fmt.Errorf("can't extract signature, unsupported "+ + "signing method: %v", signMethod) + } } // connectRPC tries to establish an RPC connection to the given host:port with From d1a151010a4e5973c0f678d133d8d8b2f7e5bad4 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 27 Apr 2022 21:05:50 +0200 Subject: [PATCH 09/13] lntest+rpcwallet: support remote p2tr script spend signing --- lntest/itest/lnd_remote_signer_test.go | 4 +- lnwallet/rpcwallet/rpcwallet.go | 60 ++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/lntest/itest/lnd_remote_signer_test.go b/lntest/itest/lnd_remote_signer_test.go index cda8fad47..2348d820e 100644 --- a/lntest/itest/lnd_remote_signer_test.go +++ b/lntest/itest/lnd_remote_signer_test.go @@ -123,12 +123,10 @@ func testRemoteSigner(net *lntest.NetworkHarness, t *harnessTest) { ) defer cancel() - // TODO(guggero): Fix remote taproot signing by adding - // the required fields to PSBT. testTaprootComputeInputScriptKeySpendBip86( ctxt, tt, wo, net, ) - // testTaprootSignOutputRawScriptSpend(ctxt, tt, wo, net) + testTaprootSignOutputRawScriptSpend(ctxt, tt, wo, net) testTaprootSignOutputRawKeySpendBip86(ctxt, tt, wo, net) testTaprootSignOutputRawKeySpendRootHash( ctxt, tt, wo, net, diff --git a/lnwallet/rpcwallet/rpcwallet.go b/lnwallet/rpcwallet/rpcwallet.go index d6d001d89..b2c468705 100644 --- a/lnwallet/rpcwallet/rpcwallet.go +++ b/lnwallet/rpcwallet/rpcwallet.go @@ -22,6 +22,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcwallet/waddrmgr" basewallet "github.com/btcsuite/btcwallet/wallet" + secp "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lncfg" @@ -1029,6 +1030,50 @@ func (r *RPCKeyRing) remoteSign(tx *wire.MsgTx, signDesc *input.SignDescriptor, // If this is a BIP0086 key spend then the tap tweak is empty, // otherwise it's set to the Taproot root hash. in.TaprootMerkleRoot = signDesc.TapTweak + + case input.TaprootScriptSpendSignMethod: + // The script spend path is a bit more involved when doing it + // through the PSBT method. We need to specify the leaf hash + // that the signer should sign for. + leaf := txscript.TapLeaf{ + LeafVersion: txscript.BaseLeafVersion, + Script: signDesc.WitnessScript, + } + leafHash := leaf.TapHash() + + d := in.Bip32Derivation[0] + in.TaprootBip32Derivation = []*psbt.TaprootBip32Derivation{{ + XOnlyPubKey: d.PubKey[1:], + LeafHashes: [][]byte{leafHash[:]}, + MasterKeyFingerprint: d.MasterKeyFingerprint, + Bip32Path: d.Bip32Path, + }} + + // We also need to supply a control block. But because we don't + // know the internal key nor the merkle proofs (both is not + // supplied through the SignOutputRaw RPC) and is technically + // not really needed by the signer (since we only want a + // signature, the full witness stack is assembled by the caller + // of this RPC), we can get by with faking certain information + // that we don't have. + fakeInternalKey, _ := btcec.ParsePubKey(d.PubKey) + fakeKeyIsOdd := d.PubKey[0] == secp.PubKeyFormatCompressedOdd + controlBlock := txscript.ControlBlock{ + InternalKey: fakeInternalKey, + OutputKeyYIsOdd: fakeKeyIsOdd, + LeafVersion: leaf.LeafVersion, + } + blockBytes, err := controlBlock.ToBytes() + if err != nil { + return nil, fmt.Errorf("error serializing control "+ + "block: %v", err) + } + + in.TaprootLeafScript = []*psbt.TaprootTapLeafScript{{ + ControlBlock: blockBytes, + Script: leaf.Script, + LeafVersion: leaf.LeafVersion, + }} } // Okay, let's sign the input by the remote signer now. @@ -1113,6 +1158,21 @@ func extractSignature(in *psbt.PInput, in.TaprootKeySpendSig[:schnorr.SignatureSize], ) + case input.TaprootScriptSpendSignMethod: + if len(in.TaprootScriptSpendSig) != 1 { + return nil, fmt.Errorf("remote signer returned "+ + "invalid taproot script spend signature, "+ + "wanted 1, got %d", + len(in.TaprootScriptSpendSig)) + } + scriptSpendSig := in.TaprootScriptSpendSig[0] + if scriptSpendSig == nil { + return nil, fmt.Errorf("remote signer returned nil " + + "taproot script spend signature") + } + + return schnorr.ParseSignature(scriptSpendSig.Signature) + default: return nil, fmt.Errorf("can't extract signature, unsupported "+ "signing method: %v", signMethod) From fe30b9e98778c7f6ce32c9a75c2a3a9818fc947b Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Thu, 28 Apr 2022 13:19:50 +0200 Subject: [PATCH 10/13] itest: refactor PSBT signing itest --- lntest/itest/lnd_psbt_test.go | 68 ++++++++++++++++++-------- lntest/itest/lnd_remote_signer_test.go | 2 +- 2 files changed, 49 insertions(+), 21 deletions(-) diff --git a/lntest/itest/lnd_psbt_test.go b/lntest/itest/lnd_psbt_test.go index 4217f9e2d..c6ecda285 100644 --- a/lntest/itest/lnd_psbt_test.go +++ b/lntest/itest/lnd_psbt_test.go @@ -632,19 +632,19 @@ func testPsbtChanFundingSingleStep(net *lntest.NetworkHarness, t *harnessTest) { closeChannelAndAssert(t, net, carol, chanPoint, false) } -// runSignPsbt tests that the SignPsbt RPC works correctly. +// testSignPsbt tests that the SignPsbt RPC works correctly. func testSignPsbt(net *lntest.NetworkHarness, t *harnessTest) { - runSignPsbt(t, net, net.Alice) + runSignPsbtSegWitV0P2WKH(t, net, net.Alice) } -// runSignPsbt tests that the SignPsbt RPC works correctly. -func runSignPsbt(t *harnessTest, net *lntest.NetworkHarness, +// runSignPsbtSegWitV0P2WKH tests that the SignPsbt RPC works correctly for a +// SegWit v0 p2wkh input. +func runSignPsbtSegWitV0P2WKH(t *harnessTest, net *lntest.NetworkHarness, alice *lntest.HarnessNode) { - ctxb := context.Background() - // Everything we do here should be done within a second or two, so we // can just keep a single timeout context around for all calls. + ctxb := context.Background() ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout) defer cancel() @@ -699,13 +699,48 @@ func runSignPsbt(t *harnessTest, net *lntest.NetworkHarness, pkScript, err := txscript.PayToAddrScript(witnessAddr) require.NoError(t.t, err) + // Send some funds to the output and then try to get a signature through + // the SignPsbt RPC to spend that output again. + assertPsbtSpend( + ctxt, t, net, alice, pkScript, + func(packet *psbt.Packet) { + in := &packet.Inputs[0] + in.Bip32Derivation = []*psbt.Bip32Derivation{{ + PubKey: addrPubKey.SerializeCompressed(), + Bip32Path: fullDerivationPath, + }} + in.SighashType = txscript.SigHashAll + }, + func(packet *psbt.Packet) { + require.Len(t.t, packet.Inputs, 1) + require.Len(t.t, packet.Inputs[0].PartialSigs, 1) + + partialSig := packet.Inputs[0].PartialSigs[0] + require.Equal( + t.t, partialSig.PubKey, + addrPubKey.SerializeCompressed(), + ) + require.Greater( + t.t, len(partialSig.Signature), ecdsa.MinSigLen, + ) + }, + ) +} + +// assertPsbtSpend creates an output with the given pkScript on chain and then +// attempts to create a sweep transaction that is signed using the SignPsbt RPC +// that spends that output again. +func assertPsbtSpend(ctx context.Context, t *harnessTest, + net *lntest.NetworkHarness, alice *lntest.HarnessNode, pkScript []byte, + decorateUnsigned func(*psbt.Packet), verifySigned func(*psbt.Packet)) { + // Let's send some coins to that address now. utxo := &wire.TxOut{ Value: 600_000, PkScript: pkScript, } resp, err := alice.WalletKitClient.SendOutputs( - ctxt, &walletrpc.SendOutputsRequest{ + ctx, &walletrpc.SendOutputsRequest{ Outputs: []*signrpc.TxOut{{ Value: utxo.Value, PkScript: utxo.PkScript, @@ -748,13 +783,9 @@ func runSignPsbt(t *harnessTest, net *lntest.NetworkHarness, require.NoError(t.t, err) // Now let's add the meta information that we need for signing. - packet.Inputs[0].Bip32Derivation = []*psbt.Bip32Derivation{{ - PubKey: addrPubKey.SerializeCompressed(), - Bip32Path: fullDerivationPath, - }} packet.Inputs[0].WitnessUtxo = utxo packet.Inputs[0].NonWitnessUtxo = prevTx - packet.Inputs[0].SighashType = txscript.SigHashAll + decorateUnsigned(packet) // That's it, we should be able to sign the PSBT now. var buf bytes.Buffer @@ -762,7 +793,7 @@ func runSignPsbt(t *harnessTest, net *lntest.NetworkHarness, require.NoError(t.t, err) signResp, err := alice.WalletKitClient.SignPsbt( - ctxt, &walletrpc.SignPsbtRequest{ + ctx, &walletrpc.SignPsbtRequest{ FundedPsbt: buf.Bytes(), }, ) @@ -774,12 +805,9 @@ func runSignPsbt(t *harnessTest, net *lntest.NetworkHarness, ) require.NoError(t.t, err) - require.Len(t.t, signedPacket.Inputs, 1) - require.Len(t.t, signedPacket.Inputs[0].PartialSigs, 1) - - partialSig := signedPacket.Inputs[0].PartialSigs[0] - require.Equal(t.t, partialSig.PubKey, addrPubKey.SerializeCompressed()) - require.Greater(t.t, len(partialSig.Signature), ecdsa.MinSigLen) + // Allow the caller to also verify (and potentially move) some of the + // returned fields. + verifySigned(signedPacket) // We should be able to finalize the PSBT and extract the final TX now. err = psbt.MaybeFinalizeAll(signedPacket) @@ -794,7 +822,7 @@ func runSignPsbt(t *harnessTest, net *lntest.NetworkHarness, // Publish the second transaction and then mine both of them. _, err = alice.WalletKitClient.PublishTransaction( - ctxt, &walletrpc.Transaction{ + ctx, &walletrpc.Transaction{ TxHex: buf.Bytes(), }, ) diff --git a/lntest/itest/lnd_remote_signer_test.go b/lntest/itest/lnd_remote_signer_test.go index 2348d820e..16f52c090 100644 --- a/lntest/itest/lnd_remote_signer_test.go +++ b/lntest/itest/lnd_remote_signer_test.go @@ -106,7 +106,7 @@ func testRemoteSigner(net *lntest.NetworkHarness, t *harnessTest) { name: "psbt", fn: func(tt *harnessTest, wo, carol *lntest.HarnessNode) { runPsbtChanFunding(net, tt, carol, wo) - runSignPsbt(tt, net, wo) + runSignPsbtSegWitV0P2WKH(tt, net, wo) }, }, { name: "sign output raw", From 6c495c1bbe0ea1fb92e8699f036b7b05df382955 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Thu, 28 Apr 2022 13:39:28 +0200 Subject: [PATCH 11/13] itest: add Taproot PSBT signing tests --- lntest/itest/lnd_psbt_test.go | 211 +++++++++++++++++++++++++ lntest/itest/lnd_remote_signer_test.go | 3 + 2 files changed, 214 insertions(+) diff --git a/lntest/itest/lnd_psbt_test.go b/lntest/itest/lnd_psbt_test.go index c6ecda285..d547fea30 100644 --- a/lntest/itest/lnd_psbt_test.go +++ b/lntest/itest/lnd_psbt_test.go @@ -6,13 +6,17 @@ import ( "crypto/rand" "fmt" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/ecdsa" + "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil/hdkeychain" "github.com/btcsuite/btcd/btcutil/psbt" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/funding" + "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc/signrpc" "github.com/lightningnetwork/lnd/lnrpc/walletrpc" @@ -635,6 +639,9 @@ func testPsbtChanFundingSingleStep(net *lntest.NetworkHarness, t *harnessTest) { // testSignPsbt tests that the SignPsbt RPC works correctly. func testSignPsbt(net *lntest.NetworkHarness, t *harnessTest) { runSignPsbtSegWitV0P2WKH(t, net, net.Alice) + runSignPsbtSegWitV1KeySpendBip86(t, net, net.Alice) + runSignPsbtSegWitV1KeySpendRootHash(t, net, net.Alice) + runSignPsbtSegWitV1ScriptSpend(t, net, net.Alice) } // runSignPsbtSegWitV0P2WKH tests that the SignPsbt RPC works correctly for a @@ -727,6 +734,182 @@ func runSignPsbtSegWitV0P2WKH(t *harnessTest, net *lntest.NetworkHarness, ) } +// runSignPsbtSegWitV1KeySpendBip86 tests that the SignPsbt RPC works correctly +// for a SegWit v1 p2tr key spend BIP-0086 input. +func runSignPsbtSegWitV1KeySpendBip86(t *harnessTest, net *lntest.NetworkHarness, + alice *lntest.HarnessNode) { + + // Everything we do here should be done within a second or two, so we + // can just keep a single timeout context around for all calls. + ctxb := context.Background() + ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout) + defer cancel() + + // Derive a key we can use for signing. + keyDesc, internalKey, fullDerivationPath := deriveInternalKey( + ctxt, t, alice, + ) + + // Our taproot key is a BIP0086 key spend only construction that just + // commits to the internal key and no root hash. + taprootKey := txscript.ComputeTaprootKeyNoScript(internalKey) + tapScriptAddr, err := btcutil.NewAddressTaproot( + schnorr.SerializePubKey(taprootKey), harnessNetParams, + ) + require.NoError(t.t, err) + p2trPkScript, err := txscript.PayToAddrScript(tapScriptAddr) + require.NoError(t.t, err) + + // Send some funds to the output and then try to get a signature through + // the SignPsbt RPC to spend that output again. + assertPsbtSpend( + ctxt, t, net, alice, p2trPkScript, + func(packet *psbt.Packet) { + in := &packet.Inputs[0] + in.Bip32Derivation = []*psbt.Bip32Derivation{{ + PubKey: keyDesc.RawKeyBytes, + Bip32Path: fullDerivationPath, + }} + in.TaprootBip32Derivation = []*psbt.TaprootBip32Derivation{{ + XOnlyPubKey: keyDesc.RawKeyBytes[1:], + Bip32Path: fullDerivationPath, + }} + in.SighashType = txscript.SigHashDefault + }, + func(packet *psbt.Packet) { + require.Len(t.t, packet.Inputs, 1) + require.Len( + t.t, packet.Inputs[0].TaprootKeySpendSig, 64, + ) + }, + ) +} + +// runSignPsbtSegWitV1KeySpendRootHash tests that the SignPsbt RPC works +// correctly for a SegWit v1 p2tr key spend that also commits to a script tree +// root hash. +func runSignPsbtSegWitV1KeySpendRootHash(t *harnessTest, + net *lntest.NetworkHarness, alice *lntest.HarnessNode) { + + // Everything we do here should be done within a second or two, so we + // can just keep a single timeout context around for all calls. + ctxb := context.Background() + ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout) + defer cancel() + + // Derive a key we can use for signing. + keyDesc, internalKey, fullDerivationPath := deriveInternalKey( + ctxt, t, alice, + ) + + // Let's create a taproot script output now. This is a hash lock with a + // simple preimage of "foobar". + leaf1 := testScriptHashLock(t.t, []byte("foobar")) + + rootHash := leaf1.TapHash() + taprootKey := txscript.ComputeTaprootOutputKey(internalKey, rootHash[:]) + tapScriptAddr, err := btcutil.NewAddressTaproot( + schnorr.SerializePubKey(taprootKey), harnessNetParams, + ) + require.NoError(t.t, err) + p2trPkScript, err := txscript.PayToAddrScript(tapScriptAddr) + require.NoError(t.t, err) + + // Send some funds to the output and then try to get a signature through + // the SignPsbt RPC to spend that output again. + assertPsbtSpend( + ctxt, t, net, alice, p2trPkScript, + func(packet *psbt.Packet) { + in := &packet.Inputs[0] + in.Bip32Derivation = []*psbt.Bip32Derivation{{ + PubKey: keyDesc.RawKeyBytes, + Bip32Path: fullDerivationPath, + }} + in.TaprootBip32Derivation = []*psbt.TaprootBip32Derivation{{ + XOnlyPubKey: keyDesc.RawKeyBytes[1:], + Bip32Path: fullDerivationPath, + }} + in.TaprootMerkleRoot = rootHash[:] + in.SighashType = txscript.SigHashDefault + }, + func(packet *psbt.Packet) { + require.Len(t.t, packet.Inputs, 1) + require.Len( + t.t, packet.Inputs[0].TaprootKeySpendSig, 64, + ) + }, + ) +} + +// runSignPsbtSegWitV1ScriptSpend tests that the SignPsbt RPC works correctly +// for a SegWit v1 p2tr script spend. +func runSignPsbtSegWitV1ScriptSpend(t *harnessTest, + net *lntest.NetworkHarness, alice *lntest.HarnessNode) { + + // Everything we do here should be done within a second or two, so we + // can just keep a single timeout context around for all calls. + ctxb := context.Background() + ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout) + defer cancel() + + // Derive a key we can use for signing. + keyDesc, internalKey, fullDerivationPath := deriveInternalKey( + ctxt, t, alice, + ) + + // Let's create a taproot script output now. This is a hash lock with a + // simple preimage of "foobar". + leaf1 := testScriptSchnorrSig(t.t, internalKey) + + rootHash := leaf1.TapHash() + taprootKey := txscript.ComputeTaprootOutputKey(internalKey, rootHash[:]) + tapScriptAddr, err := btcutil.NewAddressTaproot( + schnorr.SerializePubKey(taprootKey), harnessNetParams, + ) + require.NoError(t.t, err) + p2trPkScript, err := txscript.PayToAddrScript(tapScriptAddr) + require.NoError(t.t, err) + + // We need to assemble the control block to be able to spend through the + // script path. + tapscript := input.TapscriptPartialReveal(internalKey, leaf1, nil) + controlBlockBytes, err := tapscript.ControlBlock.ToBytes() + require.NoError(t.t, err) + + // Send some funds to the output and then try to get a signature through + // the SignPsbt RPC to spend that output again. + assertPsbtSpend( + ctxt, t, net, alice, p2trPkScript, + func(packet *psbt.Packet) { + in := &packet.Inputs[0] + in.Bip32Derivation = []*psbt.Bip32Derivation{{ + PubKey: keyDesc.RawKeyBytes, + Bip32Path: fullDerivationPath, + }} + in.TaprootBip32Derivation = []*psbt.TaprootBip32Derivation{{ + XOnlyPubKey: keyDesc.RawKeyBytes[1:], + Bip32Path: fullDerivationPath, + LeafHashes: [][]byte{rootHash[:]}, + }} + in.SighashType = txscript.SigHashDefault + in.TaprootLeafScript = []*psbt.TaprootTapLeafScript{{ + ControlBlock: controlBlockBytes, + Script: leaf1.Script, + LeafVersion: leaf1.LeafVersion, + }} + }, + func(packet *psbt.Packet) { + require.Len(t.t, packet.Inputs, 1) + require.Len( + t.t, packet.Inputs[0].TaprootScriptSpendSig, 1, + ) + + scriptSpendSig := packet.Inputs[0].TaprootScriptSpendSig[0] + require.Len(t.t, scriptSpendSig.Signature, 64) + }, + ) +} + // assertPsbtSpend creates an output with the given pkScript on chain and then // attempts to create a sweep transaction that is signed using the SignPsbt RPC // that spends that output again. @@ -836,6 +1019,34 @@ func assertPsbtSpend(ctx context.Context, t *harnessTest, assertTxInBlock(t, block, &secondTxHash) } +// deriveInternalKey derives a signing key and returns its descriptor, full +// derivation path and parsed public key. +func deriveInternalKey(ctx context.Context, t *harnessTest, + alice *lntest.HarnessNode) (*signrpc.KeyDescriptor, *btcec.PublicKey, + []uint32) { + + // For the next step, we need a public key. Let's use a special family + // for this. + keyDesc, err := alice.WalletKitClient.DeriveNextKey( + ctx, &walletrpc.KeyReq{KeyFamily: testTaprootKeyFamily}, + ) + require.NoError(t.t, err) + + // The DeriveNextKey returns a key from the internal 1017 scope. + fullDerivationPath := []uint32{ + hdkeychain.HardenedKeyStart + keychain.BIP0043Purpose, + hdkeychain.HardenedKeyStart + harnessNetParams.HDCoinType, + hdkeychain.HardenedKeyStart + uint32(keyDesc.KeyLoc.KeyFamily), + 0, + uint32(keyDesc.KeyLoc.KeyIndex), + } + + parsedPubKey, err := btcec.ParsePubKey(keyDesc.RawKeyBytes) + require.NoError(t.t, err) + + return keyDesc, parsedPubKey, fullDerivationPath +} + // openChannelPsbt attempts to open a channel between srcNode and destNode with // the passed channel funding parameters. If the passed context has a timeout, // then if the timeout is reached before the channel pending notification is diff --git a/lntest/itest/lnd_remote_signer_test.go b/lntest/itest/lnd_remote_signer_test.go index 16f52c090..1c5426a77 100644 --- a/lntest/itest/lnd_remote_signer_test.go +++ b/lntest/itest/lnd_remote_signer_test.go @@ -107,6 +107,9 @@ func testRemoteSigner(net *lntest.NetworkHarness, t *harnessTest) { fn: func(tt *harnessTest, wo, carol *lntest.HarnessNode) { runPsbtChanFunding(net, tt, carol, wo) runSignPsbtSegWitV0P2WKH(tt, net, wo) + runSignPsbtSegWitV1KeySpendBip86(tt, net, wo) + runSignPsbtSegWitV1KeySpendRootHash(tt, net, wo) + runSignPsbtSegWitV1ScriptSpend(tt, net, wo) }, }, { name: "sign output raw", From cc6e8646391fdf3f23d458334b0d531d810cae8e Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Thu, 28 Apr 2022 16:48:15 +0200 Subject: [PATCH 12/13] docs: add release notes --- docs/release-notes/release-notes-0.15.0.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/release-notes/release-notes-0.15.0.md b/docs/release-notes/release-notes-0.15.0.md index 5dbd76c90..f8dbe6a76 100644 --- a/docs/release-notes/release-notes-0.15.0.md +++ b/docs/release-notes/release-notes-0.15.0.md @@ -25,6 +25,10 @@ addresses](https://github.com/lightningnetwork/lnd/pull/6263). Using then watch it on chain. Taproot script spends are also supported through the `signrpc.SignOutputRaw` RPC (`/v2/signer/signraw` in REST). +The `walletrpc.SignPsbt` RPC now also supports [Taproot PSBT +signing](https://github.com/lightningnetwork/lnd/pull/6450) to fully support +remote signing with Taproot outputs. + ## MuSig2 The [`signrpc.Signer` RPC service now supports EXPERIMENTAL MuSig2 From 9f4f0e94f5fe2c10a915c625e41d42a508dede93 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 9 May 2022 14:09:45 +0200 Subject: [PATCH 13/13] multi: avoid direct use of dcrec/secp256k1 library Because the original dcrec secp256k1 library that is used for the Schnorr signature primitives uses different hash algorithms than the btcd secp256k1 library. Therefore pulling in the wrong library can lead to weird and unexpected errors. We try to make it harder to make the mistake by not using the library directly in lnd in the first place. Note that it is still indirectly needed by the btcd secp256k1 library, therefore the module dependency is still expected to be there, just moved to the indirect section. --- go.mod | 2 +- input/script_utils.go | 6 +++--- input/taproot.go | 16 +++++++++++++--- lnwallet/rpcwallet/rpcwallet.go | 3 +-- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 7773e4eb8..623d70b6e 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,6 @@ require ( github.com/btcsuite/btcwallet/wtxmgr v1.5.0 github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f github.com/davecgh/go-spew v1.1.1 - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 github.com/dvyukov/go-fuzz v0.0.0-20210602112143-b1f3d6f4ef4e github.com/go-errors/errors v1.0.1 github.com/golang/protobuf v1.5.2 @@ -76,6 +75,7 @@ require ( github.com/coreos/go-systemd/v22 v22.3.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect github.com/decred/dcrd/lru v1.0.0 // indirect github.com/dsnet/compress v0.0.1 // indirect github.com/dustin/go-humanize v1.0.0 // indirect diff --git a/input/script_utils.go b/input/script_utils.go index 8302a972a..e12b57c43 100644 --- a/input/script_utils.go +++ b/input/script_utils.go @@ -9,7 +9,6 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - secp "github.com/decred/dcrd/dcrec/secp256k1/v4" "golang.org/x/crypto/ripemd160" ) @@ -1399,7 +1398,7 @@ func TweakPubKeyWithTweak(pubKey *btcec.PublicKey, tweakJacobian btcec.JacobianPoint resultJacobian btcec.JacobianPoint ) - tweakKey := secp.PrivKeyFromBytes(tweakBytes) + tweakKey, _ := btcec.PrivKeyFromBytes(tweakBytes) btcec.ScalarBaseMultNonConst(&tweakKey.Key, &tweakJacobian) pubKey.AsJacobian(&pubKeyJacobian) @@ -1549,5 +1548,6 @@ func DeriveRevocationPrivKey(revokeBasePriv *btcec.PrivateKey, // the key-ring and also to used as a tweak to derive new public+private keys // for the state. func ComputeCommitmentPoint(commitSecret []byte) *btcec.PublicKey { - return secp.PrivKeyFromBytes(commitSecret).PubKey() + _, pubKey := btcec.PrivKeyFromBytes(commitSecret) + return pubKey } diff --git a/input/taproot.go b/input/taproot.go index 255fba427..0319228ba 100644 --- a/input/taproot.go +++ b/input/taproot.go @@ -7,7 +7,17 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcwallet/waddrmgr" - secp "github.com/decred/dcrd/dcrec/secp256k1/v4" +) + +const ( + // PubKeyFormatCompressedOdd is the identifier prefix byte for a public + // key whose Y coordinate is odd when serialized in the compressed + // format per section 2.3.4 of + // [SEC1](https://secg.org/sec1-v2.pdf#subsubsection.2.3.4). + // This is copied from the github.com/decred/dcrd/dcrec/secp256k1/v4 to + // avoid needing to directly reference (and by accident pull in + // incompatible crypto primitives) the package. + PubKeyFormatCompressedOdd byte = 0x03 ) // NewTxSigHashesV0Only returns a new txscript.TxSigHashes instance that will @@ -56,7 +66,7 @@ func TapscriptFullTree(internalKey *btcec.PublicKey, tapKey := txscript.ComputeTaprootOutputKey(internalKey, rootHash[:]) var outputKeyYIsOdd bool - if tapKey.SerializeCompressed()[0] == secp.PubKeyFormatCompressedOdd { + if tapKey.SerializeCompressed()[0] == PubKeyFormatCompressedOdd { outputKeyYIsOdd = true } @@ -85,7 +95,7 @@ func TapscriptPartialReveal(internalKey *btcec.PublicKey, rootHash := controlBlock.RootHash(revealedLeaf.Script) tapKey := txscript.ComputeTaprootOutputKey(internalKey, rootHash) - if tapKey.SerializeCompressed()[0] == secp.PubKeyFormatCompressedOdd { + if tapKey.SerializeCompressed()[0] == PubKeyFormatCompressedOdd { controlBlock.OutputKeyYIsOdd = true } diff --git a/lnwallet/rpcwallet/rpcwallet.go b/lnwallet/rpcwallet/rpcwallet.go index b2c468705..de47a0759 100644 --- a/lnwallet/rpcwallet/rpcwallet.go +++ b/lnwallet/rpcwallet/rpcwallet.go @@ -22,7 +22,6 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcwallet/waddrmgr" basewallet "github.com/btcsuite/btcwallet/wallet" - secp "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lncfg" @@ -1057,7 +1056,7 @@ func (r *RPCKeyRing) remoteSign(tx *wire.MsgTx, signDesc *input.SignDescriptor, // of this RPC), we can get by with faking certain information // that we don't have. fakeInternalKey, _ := btcec.ParsePubKey(d.PubKey) - fakeKeyIsOdd := d.PubKey[0] == secp.PubKeyFormatCompressedOdd + fakeKeyIsOdd := d.PubKey[0] == input.PubKeyFormatCompressedOdd controlBlock := txscript.ControlBlock{ InternalKey: fakeInternalKey, OutputKeyYIsOdd: fakeKeyIsOdd,