mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 09:53:54 +01:00
multi: add p2tr tapscript signing capabilities
This commit is contained in:
parent
5109c55721
commit
78db46be7e
@ -3,6 +3,7 @@ package input
|
||||
import (
|
||||
"github.com/btcsuite/btcd/blockchain"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcwallet/waddrmgr"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -532,11 +533,16 @@ const (
|
||||
// - witness_script (anchor_script)
|
||||
AnchorWitnessSize = 1 + 1 + 73 + 1 + AnchorScriptSize
|
||||
|
||||
// TaprootSignatureWitnessSize 65 bytes
|
||||
// - sigLength: 1 byte
|
||||
// - sig: 64 bytes
|
||||
TaprootSignatureWitnessSize = 1 + 64
|
||||
|
||||
// TaprootKeyPathWitnessSize 66 bytes
|
||||
// - NumberOfWitnessElements: 1 byte
|
||||
// - sigLength: 1 byte
|
||||
// - sig: 64 bytes
|
||||
TaprootKeyPathWitnessSize = 1 + 1 + 64
|
||||
TaprootKeyPathWitnessSize = 1 + TaprootSignatureWitnessSize
|
||||
|
||||
// TaprootKeyPathCustomSighashWitnessSize 67 bytes
|
||||
// - NumberOfWitnessElements: 1 byte
|
||||
@ -544,6 +550,11 @@ const (
|
||||
// - sig: 64 bytes
|
||||
// - sighashFlag: 1 byte
|
||||
TaprootKeyPathCustomSighashWitnessSize = TaprootKeyPathWitnessSize + 1
|
||||
|
||||
// TaprootBaseControlBlockWitnessSize 33 bytes
|
||||
// - leafVersionAndParity: 1 byte
|
||||
// - schnorrPubKey: 32 byte
|
||||
TaprootBaseControlBlockWitnessSize = 33
|
||||
)
|
||||
|
||||
// EstimateCommitTxWeight estimate commitment transaction weight depending on
|
||||
@ -607,6 +618,31 @@ func (twe *TxWeightEstimator) AddWitnessInput(witnessSize int) *TxWeightEstimato
|
||||
return twe
|
||||
}
|
||||
|
||||
// AddTapscriptInput updates the weight estimate to account for an additional
|
||||
// input spending a segwit v1 pay-to-taproot output using the script path. This
|
||||
// accepts the total size of the witness for the script leaf that is executed
|
||||
// and adds the size of the control block to the total witness size.
|
||||
//
|
||||
// NOTE: The leaf witness size must be calculated without the byte that accounts
|
||||
// for the number of witness elements, only the total size of all elements on
|
||||
// the stack that are consumed by the revealed script should be counted.
|
||||
func (twe *TxWeightEstimator) AddTapscriptInput(leafWitnessSize int,
|
||||
tapscript *waddrmgr.Tapscript) *TxWeightEstimator {
|
||||
|
||||
// We add 1 byte for the total number of witness elements.
|
||||
controlBlockWitnessSize := 1 + TaprootBaseControlBlockWitnessSize +
|
||||
// 1 byte for the length of the element plus the element itself.
|
||||
1 + len(tapscript.RevealedScript) +
|
||||
1 + len(tapscript.ControlBlock.InclusionProof)
|
||||
|
||||
twe.inputSize += InputSize
|
||||
twe.inputWitnessSize += leafWitnessSize + controlBlockWitnessSize
|
||||
twe.inputCount++
|
||||
twe.hasWitness = true
|
||||
|
||||
return twe
|
||||
}
|
||||
|
||||
// AddNestedP2WKHInput updates the weight estimate to account for an additional
|
||||
// input spending a P2SH output with a nested P2WKH redeem script.
|
||||
func (twe *TxWeightEstimator) AddNestedP2WKHInput() *TxWeightEstimator {
|
||||
|
@ -334,6 +334,10 @@ type SignReq struct {
|
||||
RawTxBytes []byte `protobuf:"bytes,1,opt,name=raw_tx_bytes,json=rawTxBytes,proto3" json:"raw_tx_bytes,omitempty"`
|
||||
// A set of sign descriptors, for each input to be signed.
|
||||
SignDescs []*SignDescriptor `protobuf:"bytes,2,rep,name=sign_descs,json=signDescs,proto3" json:"sign_descs,omitempty"`
|
||||
//
|
||||
//The full list of UTXO information for each of the inputs being spent. This
|
||||
//is required when spending one or more taproot (SegWit v1) outputs.
|
||||
PrevOutputs []*TxOut `protobuf:"bytes,3,rep,name=prev_outputs,json=prevOutputs,proto3" json:"prev_outputs,omitempty"`
|
||||
}
|
||||
|
||||
func (x *SignReq) Reset() {
|
||||
@ -382,6 +386,13 @@ func (x *SignReq) GetSignDescs() []*SignDescriptor {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *SignReq) GetPrevOutputs() []*TxOut {
|
||||
if x != nil {
|
||||
return x.PrevOutputs
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type SignResp struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@ -940,85 +951,88 @@ var file_signrpc_signer_proto_rawDesc = []byte{
|
||||
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, 0x22, 0x63,
|
||||
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, 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,
|
||||
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, 0x32, 0xd4, 0x02, 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, 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,
|
||||
0x28, 0x05, 0x52, 0x0a, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 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, 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, 0x32, 0xd4, 0x02, 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, 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 (
|
||||
@ -1055,25 +1069,26 @@ var file_signrpc_signer_proto_depIdxs = []int32{
|
||||
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
|
||||
6, // 4: signrpc.InputScriptResp.input_scripts:type_name -> signrpc.InputScript
|
||||
0, // 5: signrpc.SignMessageReq.key_loc:type_name -> signrpc.KeyLocator
|
||||
0, // 6: signrpc.SharedKeyRequest.key_loc:type_name -> signrpc.KeyLocator
|
||||
1, // 7: signrpc.SharedKeyRequest.key_desc:type_name -> signrpc.KeyDescriptor
|
||||
4, // 8: signrpc.Signer.SignOutputRaw:input_type -> signrpc.SignReq
|
||||
4, // 9: signrpc.Signer.ComputeInputScript:input_type -> signrpc.SignReq
|
||||
8, // 10: signrpc.Signer.SignMessage:input_type -> signrpc.SignMessageReq
|
||||
10, // 11: signrpc.Signer.VerifyMessage:input_type -> signrpc.VerifyMessageReq
|
||||
12, // 12: signrpc.Signer.DeriveSharedKey:input_type -> signrpc.SharedKeyRequest
|
||||
5, // 13: signrpc.Signer.SignOutputRaw:output_type -> signrpc.SignResp
|
||||
7, // 14: signrpc.Signer.ComputeInputScript:output_type -> signrpc.InputScriptResp
|
||||
9, // 15: signrpc.Signer.SignMessage:output_type -> signrpc.SignMessageResp
|
||||
11, // 16: signrpc.Signer.VerifyMessage:output_type -> signrpc.VerifyMessageResp
|
||||
13, // 17: signrpc.Signer.DeriveSharedKey:output_type -> signrpc.SharedKeyResponse
|
||||
13, // [13:18] is the sub-list for method output_type
|
||||
8, // [8:13] is the sub-list for method input_type
|
||||
8, // [8:8] is the sub-list for extension type_name
|
||||
8, // [8:8] is the sub-list for extension extendee
|
||||
0, // [0:8] is the sub-list for field type_name
|
||||
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
|
||||
4, // 9: signrpc.Signer.SignOutputRaw:input_type -> signrpc.SignReq
|
||||
4, // 10: signrpc.Signer.ComputeInputScript:input_type -> signrpc.SignReq
|
||||
8, // 11: signrpc.Signer.SignMessage:input_type -> signrpc.SignMessageReq
|
||||
10, // 12: signrpc.Signer.VerifyMessage:input_type -> signrpc.VerifyMessageReq
|
||||
12, // 13: signrpc.Signer.DeriveSharedKey:input_type -> signrpc.SharedKeyRequest
|
||||
5, // 14: signrpc.Signer.SignOutputRaw:output_type -> signrpc.SignResp
|
||||
7, // 15: signrpc.Signer.ComputeInputScript:output_type -> signrpc.InputScriptResp
|
||||
9, // 16: signrpc.Signer.SignMessage:output_type -> signrpc.SignMessageResp
|
||||
11, // 17: signrpc.Signer.VerifyMessage:output_type -> signrpc.VerifyMessageResp
|
||||
13, // 18: signrpc.Signer.DeriveSharedKey:output_type -> signrpc.SharedKeyResponse
|
||||
14, // [14:19] is the sub-list for method output_type
|
||||
9, // [9:14] is the sub-list for method input_type
|
||||
9, // [9:9] is the sub-list for extension type_name
|
||||
9, // [9:9] is the sub-list for extension extendee
|
||||
0, // [0:9] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_signrpc_signer_proto_init() }
|
||||
|
@ -158,6 +158,12 @@ message SignReq {
|
||||
|
||||
// A set of sign descriptors, for each input to be signed.
|
||||
repeated SignDescriptor sign_descs = 2;
|
||||
|
||||
/*
|
||||
The full list of UTXO information for each of the inputs being spent. This
|
||||
is required when spending one or more taproot (SegWit v1) outputs.
|
||||
*/
|
||||
repeated TxOut prev_outputs = 3;
|
||||
}
|
||||
|
||||
message SignResp {
|
||||
|
@ -389,6 +389,13 @@
|
||||
"$ref": "#/definitions/signrpcSignDescriptor"
|
||||
},
|
||||
"description": "A set of sign descriptors, for each input to be signed."
|
||||
},
|
||||
"prev_outputs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/signrpcTxOut"
|
||||
},
|
||||
"description": "The full list of UTXO information for each of the inputs being spent. This\nis required when spending one or more taproot (SegWit v1) outputs."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -238,7 +238,7 @@ func (r *ServerShell) CreateSubServer(configRegistry lnrpc.SubServerConfigDispat
|
||||
// provides an invalid transaction, then we'll return with an error.
|
||||
//
|
||||
// NOTE: The resulting signature should be void of a sighash byte.
|
||||
func (s *Server) SignOutputRaw(ctx context.Context, in *SignReq) (*SignResp,
|
||||
func (s *Server) SignOutputRaw(_ context.Context, in *SignReq) (*SignResp,
|
||||
error) {
|
||||
|
||||
switch {
|
||||
@ -266,7 +266,33 @@ func (s *Server) SignOutputRaw(ctx context.Context, in *SignReq) (*SignResp,
|
||||
return nil, fmt.Errorf("unable to decode tx: %v", err)
|
||||
}
|
||||
|
||||
sigHashCache := input.NewTxSigHashesV0Only(&txToSign)
|
||||
var (
|
||||
sigHashCache = input.NewTxSigHashesV0Only(&txToSign)
|
||||
prevOutputFetcher = txscript.NewMultiPrevOutFetcher(nil)
|
||||
)
|
||||
|
||||
// If we're spending one or more SegWit v1 (Taproot) inputs, then we
|
||||
// need the full UTXO information available.
|
||||
if len(in.PrevOutputs) > 0 {
|
||||
if len(in.PrevOutputs) != len(txToSign.TxIn) {
|
||||
return nil, fmt.Errorf("provided previous outputs " +
|
||||
"doesn't match number of transaction inputs")
|
||||
}
|
||||
|
||||
// Add all previous inputs to our sighash prev out fetcher so we
|
||||
// can calculate the sighash correctly.
|
||||
for idx, txIn := range txToSign.TxIn {
|
||||
prevOutputFetcher.AddPrevOut(
|
||||
txIn.PreviousOutPoint, &wire.TxOut{
|
||||
Value: in.PrevOutputs[idx].Value,
|
||||
PkScript: in.PrevOutputs[idx].PkScript,
|
||||
},
|
||||
)
|
||||
}
|
||||
sigHashCache = txscript.NewTxSigHashes(
|
||||
&txToSign, prevOutputFetcher,
|
||||
)
|
||||
}
|
||||
|
||||
log.Debugf("Generating sigs for %v inputs: ", len(in.SignDescs))
|
||||
|
||||
@ -344,9 +370,10 @@ func (s *Server) SignOutputRaw(ctx context.Context, in *SignReq) (*SignResp,
|
||||
Value: signDesc.Output.Value,
|
||||
PkScript: signDesc.Output.PkScript,
|
||||
},
|
||||
HashType: txscript.SigHashType(signDesc.Sighash),
|
||||
SigHashes: sigHashCache,
|
||||
InputIndex: int(signDesc.InputIndex),
|
||||
HashType: txscript.SigHashType(signDesc.Sighash),
|
||||
SigHashes: sigHashCache,
|
||||
InputIndex: int(signDesc.InputIndex),
|
||||
PrevOutputFetcher: prevOutputFetcher,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,23 @@
|
||||
package itest
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/blockchain"
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/btcec/v2/schnorr"
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@ -16,6 +28,15 @@ func testTaproot(net *lntest.NetworkHarness, t *harnessTest) {
|
||||
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
|
||||
defer cancel()
|
||||
|
||||
testTaprootKeySpend(ctxt, t, net)
|
||||
testTaprootScriptSpend(ctxt, t, net)
|
||||
}
|
||||
|
||||
// testTaprootKeySpend tests sending to and spending from p2tr key spend only
|
||||
// (BIP-0086) addresses.
|
||||
func testTaprootKeySpend(ctxt context.Context, t *harnessTest,
|
||||
net *lntest.NetworkHarness) {
|
||||
|
||||
// We'll start the test by sending Alice some coins, which she'll use to
|
||||
// send to herself on a p2tr output.
|
||||
net.SendCoins(t.t, btcutil.SatoshiPerBitcoin, net.Alice)
|
||||
@ -81,3 +102,204 @@ func testTaproot(net *lntest.NetworkHarness, t *harnessTest) {
|
||||
// Mine another block to clean up the mempool.
|
||||
mineBlocks(t, net, 1, 1)
|
||||
}
|
||||
|
||||
// testTaprootScriptSpend tests sending to and spending from p2tr script
|
||||
// addresses.
|
||||
func testTaprootScriptSpend(ctxt context.Context, t *harnessTest,
|
||||
net *lntest.NetworkHarness) {
|
||||
|
||||
// For the next step, we need a public key. Let's use a special family
|
||||
// for this.
|
||||
const taprootKeyFamily = 77
|
||||
keyDesc, err := net.Alice.WalletKitClient.DeriveNextKey(
|
||||
ctxt, &walletrpc.KeyReq{
|
||||
KeyFamily: taprootKeyFamily,
|
||||
},
|
||||
)
|
||||
require.NoError(t.t, err)
|
||||
|
||||
leafSigningKey, err := btcec.ParsePubKey(keyDesc.RawKeyBytes)
|
||||
require.NoError(t.t, err)
|
||||
|
||||
// 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"))
|
||||
|
||||
// Let's add a second script output as well to test the partial reveal.
|
||||
leaf2 := testScriptSchnorrSig(t.t, leafSigningKey)
|
||||
|
||||
dummyInternalKeyBytes, _ := hex.DecodeString(
|
||||
"03464805f5468e294d88cf15a3f06aef6c89d63ef1bd7b42db2e0c74c1ac" +
|
||||
"eb90fe",
|
||||
)
|
||||
dummyInternalKey, _ := btcec.ParsePubKey(dummyInternalKeyBytes)
|
||||
|
||||
tapscript := input.TapscriptPartialReveal(
|
||||
dummyInternalKey, leaf2, leaf1.TapHash(),
|
||||
)
|
||||
taprootKey, err := tapscript.TaprootKey()
|
||||
require.NoError(t.t, err)
|
||||
|
||||
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 coins to the generated tapscript address.
|
||||
_, err = net.Alice.SendCoins(ctxt, &lnrpc.SendCoinsRequest{
|
||||
Addr: tapScriptAddr.String(),
|
||||
Amount: 800_000,
|
||||
})
|
||||
require.NoError(t.t, err)
|
||||
|
||||
// Wait until the TX is found in the mempool.
|
||||
txid, err := waitForTxInMempool(net.Miner.Client, minerMempoolTimeout)
|
||||
require.NoError(t.t, err)
|
||||
|
||||
p2trOutputIndex := getOutputIndex(
|
||||
t, net.Miner, txid, tapScriptAddr.String(),
|
||||
)
|
||||
|
||||
// Clear the mempool.
|
||||
mineBlocks(t, net, 1, 1)
|
||||
|
||||
// Spend the output again, this time back to a p2wkh address.
|
||||
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
|
||||
ctxt, t.t, net.Alice, lnrpc.AddressType_WITNESS_PUBKEY_HASH,
|
||||
)
|
||||
|
||||
// Create fee estimation for a p2tr input and p2wkh output.
|
||||
feeRate := chainfee.SatPerKWeight(12500)
|
||||
estimator := input.TxWeightEstimator{}
|
||||
estimator.AddTapscriptInput(
|
||||
input.TaprootSignatureWitnessSize, tapscript,
|
||||
)
|
||||
estimator.AddP2WKHOutput()
|
||||
estimatedWeight := int64(estimator.Weight())
|
||||
requiredFee := feeRate.FeeForWeight(estimatedWeight)
|
||||
|
||||
tx := wire.NewMsgTx(2)
|
||||
tx.TxIn = []*wire.TxIn{{
|
||||
PreviousOutPoint: wire.OutPoint{
|
||||
Hash: *txid,
|
||||
Index: uint32(p2trOutputIndex),
|
||||
},
|
||||
}}
|
||||
value := int64(800_000 - requiredFee)
|
||||
tx.TxOut = []*wire.TxOut{{
|
||||
PkScript: p2wkhPkScript,
|
||||
Value: value,
|
||||
}}
|
||||
|
||||
var buf bytes.Buffer
|
||||
require.NoError(t.t, tx.Serialize(&buf))
|
||||
|
||||
utxoInfo := []*signrpc.TxOut{{
|
||||
PkScript: p2trPkScript,
|
||||
Value: 800_000,
|
||||
}}
|
||||
signResp, err := net.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.NoError(t.t, err)
|
||||
|
||||
// We can now assemble the witness stack.
|
||||
controlBlockBytes, err := tapscript.ControlBlock.ToBytes()
|
||||
require.NoError(t.t, err)
|
||||
|
||||
tx.TxIn[0].Witness = wire.TxWitness{
|
||||
signResp.RawSigs[0],
|
||||
leaf2.Script,
|
||||
controlBlockBytes,
|
||||
}
|
||||
|
||||
buf.Reset()
|
||||
require.NoError(t.t, tx.Serialize(&buf))
|
||||
|
||||
// Since Schnorr signatures are fixed size, we must be able to estimate
|
||||
// the size of this transaction exactly.
|
||||
txWeight := blockchain.GetTransactionWeight(btcutil.NewTx(tx))
|
||||
require.Equal(t.t, txWeight, estimatedWeight)
|
||||
|
||||
_, err = net.Alice.WalletKitClient.PublishTransaction(
|
||||
ctxt, &walletrpc.Transaction{
|
||||
TxHex: buf.Bytes(),
|
||||
},
|
||||
)
|
||||
require.NoError(t.t, err)
|
||||
|
||||
// Wait until the spending tx is found.
|
||||
txid, err = waitForTxInMempool(net.Miner.Client, minerMempoolTimeout)
|
||||
require.NoError(t.t, err)
|
||||
p2wpkhOutputIndex := getOutputIndex(
|
||||
t, net.Miner, txid, p2wkhAddr.String(),
|
||||
)
|
||||
op := &lnrpc.OutPoint{
|
||||
TxidBytes: txid[:],
|
||||
OutputIndex: uint32(p2wpkhOutputIndex),
|
||||
}
|
||||
assertWalletUnspent(t, net.Alice, op)
|
||||
|
||||
// Mine another block to clean up the mempool and to make sure the spend
|
||||
// tx is actually included in a block.
|
||||
mineBlocks(t, net, 1, 1)
|
||||
}
|
||||
|
||||
// testScriptHashLock returns a simple bitcoin script that locks the funds to
|
||||
// a hash lock of the given preimage.
|
||||
func testScriptHashLock(t *testing.T, preimage []byte) txscript.TapLeaf {
|
||||
builder := txscript.NewScriptBuilder()
|
||||
builder.AddOp(txscript.OP_DUP)
|
||||
builder.AddOp(txscript.OP_HASH160)
|
||||
builder.AddData(btcutil.Hash160(preimage))
|
||||
builder.AddOp(txscript.OP_EQUALVERIFY)
|
||||
script1, err := builder.Script()
|
||||
require.NoError(t, err)
|
||||
return txscript.NewBaseTapLeaf(script1)
|
||||
}
|
||||
|
||||
// testScriptSchnorrSig returns a simple bitcoin script that locks the funds to
|
||||
// a Schnorr signature of the given public key.
|
||||
func testScriptSchnorrSig(t *testing.T,
|
||||
pubKey *btcec.PublicKey) txscript.TapLeaf {
|
||||
|
||||
builder := txscript.NewScriptBuilder()
|
||||
builder.AddData(schnorr.SerializePubKey(pubKey))
|
||||
builder.AddOp(txscript.OP_CHECKSIG)
|
||||
script2, err := builder.Script()
|
||||
require.NoError(t, err)
|
||||
return txscript.NewBaseTapLeaf(script2)
|
||||
}
|
||||
|
||||
// newAddrWithScript returns a new address and its pkScript.
|
||||
func newAddrWithScript(ctx context.Context, t *testing.T,
|
||||
node *lntest.HarnessNode, addrType lnrpc.AddressType) (btcutil.Address,
|
||||
[]byte) {
|
||||
|
||||
p2wkhResp, err := node.NewAddress(ctx, &lnrpc.NewAddressRequest{
|
||||
Type: addrType,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
p2wkhAddr, err := btcutil.DecodeAddress(
|
||||
p2wkhResp.Address, harnessNetParams,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
p2wkhPkScript, err := txscript.PayToAddrScript(p2wkhAddr)
|
||||
require.NoError(t, err)
|
||||
|
||||
return p2wkhAddr, p2wkhPkScript
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
|
||||
"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/chaincfg/chainhash"
|
||||
@ -356,6 +357,33 @@ func (b *BtcWallet) SignOutputRaw(tx *wire.MsgTx,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// In case of a taproot output any signature is always a Schnorr
|
||||
// signature, based on the new tapscript sighash algorithm.
|
||||
if txscript.IsPayToTaproot(signDesc.Output.PkScript) {
|
||||
sigHashes := txscript.NewTxSigHashes(
|
||||
tx, signDesc.PrevOutputFetcher,
|
||||
)
|
||||
leaf := txscript.TapLeaf{
|
||||
LeafVersion: txscript.BaseLeafVersion,
|
||||
Script: witnessScript,
|
||||
}
|
||||
rawSig, err := txscript.RawTxInTapscriptSignature(
|
||||
tx, sigHashes, signDesc.InputIndex,
|
||||
signDesc.Output.Value, signDesc.Output.PkScript,
|
||||
leaf, signDesc.HashType, privKey,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sig, err := schnorr.ParseSignature(rawSig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return sig, nil
|
||||
}
|
||||
|
||||
// TODO(roasbeef): generate sighash midstate if not present?
|
||||
|
||||
amt := signDesc.Output.Value
|
||||
|
Loading…
Reference in New Issue
Block a user