Skip to content

Commit

Permalink
multi: add p2tr keyspend wallet support
Browse files Browse the repository at this point in the history
  • Loading branch information
guggero committed Mar 24, 2022
1 parent f130edd commit c73cf03
Show file tree
Hide file tree
Showing 24 changed files with 416 additions and 163 deletions.
5 changes: 4 additions & 1 deletion cmd/lncli/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@ var newAddressCommand = cli.Command{
Description: `
Generate a wallet new address. Address-types has to be one of:
- p2wkh: Pay to witness key hash
- np2wkh: Pay to nested witness key hash`,
- np2wkh: Pay to nested witness key hash
- p2tr: Pay to taproot pubkey`,
Action: actionDecorator(newAddress),
}

Expand All @@ -161,6 +162,8 @@ func newAddress(ctx *cli.Context) error {
addrType = lnrpc.AddressType_WITNESS_PUBKEY_HASH
case "np2wkh":
addrType = lnrpc.AddressType_NESTED_PUBKEY_HASH
case "p2tr":
addrType = lnrpc.AddressType_TAPROOT_PUBKEY
default:
return fmt.Errorf("invalid address type %v, support address type "+
"are: p2wkh and np2wkh", stringAddrType)
Expand Down
9 changes: 8 additions & 1 deletion config_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -1112,7 +1112,14 @@ func importWatchOnlyAccounts(wallet *wallet.Wallet,

for _, scope := range scopes {
addrSchema := waddrmgr.ScopeAddrMap[waddrmgr.KeyScopeBIP0084]
if scope.Scope.Purpose == waddrmgr.KeyScopeBIP0049Plus.Purpose {

// We want witness pubkey hash by default, except for BIP49
// where we want mixed and BIP86 where we want taproot address
// formats.
switch scope.Scope.Purpose {
case waddrmgr.KeyScopeBIP0049Plus.Purpose,
waddrmgr.KeyScopeBIP0086.Purpose:

addrSchema = waddrmgr.ScopeAddrMap[scope.Scope]
}

Expand Down
34 changes: 34 additions & 0 deletions input/size.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,18 @@ const (
// - pkscript (p2sh): 23 bytes
P2SHOutputSize = 8 + 1 + P2SHSize

// P2TRSize 34 bytes
// - OP_0: 1 byte
// - OP_DATA: 1 byte (x-only public key length)
// - x-only public key length: 32 bytes
P2TRSize = 34

// P2TROutputSize 43 bytes
// - value: 8 bytes
// - var_int: 1 byte (pkscript_length)
// - pkscript (p2tr): 34 bytes
P2TROutputSize = 8 + 1 + P2TRSize

// P2PKHScriptSigSize 108 bytes
// - OP_DATA: 1 byte (signature length)
// - signature
Expand Down Expand Up @@ -519,6 +531,19 @@ const (
// - witness_script_length: 1 byte
// - witness_script (anchor_script)
AnchorWitnessSize = 1 + 1 + 73 + 1 + AnchorScriptSize

// TaprootKeyPathWitnessSize 66 bytes
// - NumberOfWitnessElements: 1 byte
// - sigLength: 1 byte
// - sig: 64 bytes
TaprootKeyPathWitnessSize = 1 + 1 + 64

// TaprootKeyPathCustomSighashWitnessSize 67 bytes
// - NumberOfWitnessElements: 1 byte
// - sigLength: 1 byte
// - sig: 64 bytes
// - sighashFlag: 1 byte
TaprootKeyPathCustomSighashWitnessSize = TaprootKeyPathWitnessSize + 1
)

// EstimateCommitTxWeight estimate commitment transaction weight depending on
Expand Down Expand Up @@ -639,6 +664,15 @@ func (twe *TxWeightEstimator) AddP2WSHOutput() *TxWeightEstimator {
return twe
}

// AddP2TROutput updates the weight estimate to account for an additional native
// SegWit v1 P2TR output.
func (twe *TxWeightEstimator) AddP2TROutput() *TxWeightEstimator {
twe.outputSize += P2TROutputSize
twe.outputCount++

return twe
}

// AddP2SHOutput updates the weight estimate to account for an additional P2SH
// output.
func (twe *TxWeightEstimator) AddP2SHOutput() *TxWeightEstimator {
Expand Down
13 changes: 13 additions & 0 deletions input/witnessgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,11 @@ const (
// and CLTV locktime as part of the script enforced lease commitment
// type.
LeaseHtlcAcceptedSuccessSecondLevel StandardWitnessType = 20

// TaprootPubKeySpend is a witness type that allows us to spend a
// regular p2tr output that's sent to an output which is under complete
// control of the backing wallet.
TaprootPubKeySpend StandardWitnessType = 21
)

// String returns a human readable version of the target WitnessType.
Expand Down Expand Up @@ -245,6 +250,9 @@ func (wt StandardWitnessType) String() string {
case LeaseHtlcAcceptedSuccessSecondLevel:
return "LeaseHtlcAcceptedSuccessSecondLevel"

case TaprootPubKeySpend:
return "TaprootPubKeySpend"

default:
return fmt.Sprintf("Unknown WitnessType: %v", uint32(wt))
}
Expand Down Expand Up @@ -388,6 +396,8 @@ func (wt StandardWitnessType) WitnessGenerator(signer Signer,

case WitnessKeyHash:
fallthrough
case TaprootPubKeySpend:
fallthrough
case NestedWitnessKeyHash:
return signer.ComputeInputScript(tx, desc)

Expand Down Expand Up @@ -494,6 +504,9 @@ func (wt StandardWitnessType) SizeUpperBound() (int, bool, error) {
// The revocation output of a second level output of an HTLC.
case HtlcSecondLevelRevoke:
return ToLocalPenaltyWitnessSize, false, nil

case TaprootPubKeySpend:
return TaprootKeyPathCustomSighashWitnessSize, false, nil
}

return 0, false, fmt.Errorf("unexpected witness type: %v", wt)
Expand Down
28 changes: 19 additions & 9 deletions lnrpc/lightning.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions lnrpc/lightning.proto
Original file line number Diff line number Diff line change
Expand Up @@ -1138,12 +1138,15 @@ message ListUnspentResponse {
- `p2wkh`: Pay to witness key hash (`WITNESS_PUBKEY_HASH` = 0)
- `np2wkh`: Pay to nested witness key hash (`NESTED_PUBKEY_HASH` = 1)
- `p2tr`: Pay to taproot pubkey (`TAPROOT_PUBKEY` = 4)
*/
enum AddressType {
WITNESS_PUBKEY_HASH = 0;
NESTED_PUBKEY_HASH = 1;
UNUSED_WITNESS_PUBKEY_HASH = 2;
UNUSED_NESTED_PUBKEY_HASH = 3;
TAPROOT_PUBKEY = 4;
UNUSED_TAPROOT_PUBKEY = 5;
}

message NewAddressRequest {
Expand Down
10 changes: 7 additions & 3 deletions lnrpc/lightning.swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -1801,7 +1801,9 @@
"WITNESS_PUBKEY_HASH",
"NESTED_PUBKEY_HASH",
"UNUSED_WITNESS_PUBKEY_HASH",
"UNUSED_NESTED_PUBKEY_HASH"
"UNUSED_NESTED_PUBKEY_HASH",
"TAPROOT_PUBKEY",
"UNUSED_TAPROOT_PUBKEY"
],
"default": "WITNESS_PUBKEY_HASH"
},
Expand Down Expand Up @@ -2923,10 +2925,12 @@
"WITNESS_PUBKEY_HASH",
"NESTED_PUBKEY_HASH",
"UNUSED_WITNESS_PUBKEY_HASH",
"UNUSED_NESTED_PUBKEY_HASH"
"UNUSED_NESTED_PUBKEY_HASH",
"TAPROOT_PUBKEY",
"UNUSED_TAPROOT_PUBKEY"
],
"default": "WITNESS_PUBKEY_HASH",
"description": "- `p2wkh`: Pay to witness key hash (`WITNESS_PUBKEY_HASH` = 0)\n- `np2wkh`: Pay to nested witness key hash (`NESTED_PUBKEY_HASH` = 1)",
"description": "- `p2wkh`: Pay to witness key hash (`WITNESS_PUBKEY_HASH` = 0)\n- `np2wkh`: Pay to nested witness key hash (`NESTED_PUBKEY_HASH` = 1)\n- `p2tr`: Pay to taproot pubkey (`TAPROOT_PUBKEY` = 4)",
"title": "`AddressType` has to be one of:"
},
"lnrpcAmount": {
Expand Down
3 changes: 3 additions & 0 deletions lnrpc/marshall_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ func MarshalUtxos(utxos []*lnwallet.Utxo, activeNetParams *chaincfg.Params) (
case lnwallet.NestedWitnessPubKey:
addrType = AddressType_NESTED_PUBKEY_HASH

case lnwallet.TaprootPubkey:
addrType = AddressType_TAPROOT_PUBKEY

case lnwallet.UnknownAddressType:
continue

Expand Down
Loading

0 comments on commit c73cf03

Please sign in to comment.