Skip to content

Commit

Permalink
Merge pull request #7464 from guggero/script-builder-capacity
Browse files Browse the repository at this point in the history
input: reduce memory allocation for ScriptBuilder
  • Loading branch information
Roasbeef committed Apr 11, 2023
2 parents 30010db + 26254d0 commit 158e93f
Show file tree
Hide file tree
Showing 6 changed files with 270 additions and 43 deletions.
29 changes: 6 additions & 23 deletions channeldb/graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/aliasmgr"
"github.com/lightningnetwork/lnd/batch"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/kvdb"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing/route"
Expand Down Expand Up @@ -3731,35 +3732,17 @@ func (c *ChannelGraph) IsPublicNode(pubKey [33]byte) (bool, error) {

// genMultiSigP2WSH generates the p2wsh'd multisig script for 2 of 2 pubkeys.
func genMultiSigP2WSH(aPub, bPub []byte) ([]byte, error) {
if len(aPub) != 33 || len(bPub) != 33 {
return nil, fmt.Errorf("pubkey size error. Compressed " +
"pubkeys only")
}

// Swap to sort pubkeys if needed. Keys are sorted in lexicographical
// order. The signatures within the scriptSig must also adhere to the
// order, ensuring that the signatures for each public key appears in
// the proper order on the stack.
if bytes.Compare(aPub, bPub) == 1 {
aPub, bPub = bPub, aPub
}

// First, we'll generate the witness script for the multi-sig.
bldr := txscript.NewScriptBuilder()
bldr.AddOp(txscript.OP_2)
bldr.AddData(aPub) // Add both pubkeys (sorted).
bldr.AddData(bPub)
bldr.AddOp(txscript.OP_2)
bldr.AddOp(txscript.OP_CHECKMULTISIG)
witnessScript, err := bldr.Script()
witnessScript, err := input.GenMultiSigScript(aPub, bPub)
if err != nil {
return nil, err
}

// With the witness script generated, we'll now turn it into a p2sh
// With the witness script generated, we'll now turn it into a p2wsh
// script:
// * OP_0 <sha256(script)>
bldr = txscript.NewScriptBuilder()
bldr := txscript.NewScriptBuilder(
txscript.WithScriptAllocSize(input.P2WSHSize),
)
bldr.AddOp(txscript.OP_0)
scriptHash := sha256.Sum256(witnessScript)
bldr.AddData(scriptHash[:])
Expand Down
5 changes: 4 additions & 1 deletion docs/release-notes/release-notes-0.16.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ https://github.com/lightningnetwork/lnd/pull/7359)

* [Return `FEE_INSUFFICIENT` before checking balance for incoming low-fee
HTLCs.](https://github.com/lightningnetwork/lnd/pull/7490).


* Optimize script allocation size in order to save
[memory](https://github.com/lightningnetwork/lnd/pull/7464).

## Spec

* [Add test vectors for
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/lightningnetwork/lnd
require (
github.com/NebulousLabs/go-upnp v0.0.0-20180202185039-29b680b06c82
github.com/Yawning/aez v0.0.0-20211027044916-e49e68abd344
github.com/btcsuite/btcd v0.23.5-0.20230125025938-be056b0a0b2f
github.com/btcsuite/btcd v0.23.5-0.20230228185050-38331963bddd
github.com/btcsuite/btcd/btcec/v2 v2.3.2
github.com/btcsuite/btcd/btcutil v1.1.3
github.com/btcsuite/btcd/btcutil/psbt v1.1.8
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ github.com/btcsuite/btcd v0.22.0-beta.0.20220207191057-4dc4ff7963b4/go.mod h1:7a
github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY=
github.com/btcsuite/btcd v0.23.1/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY=
github.com/btcsuite/btcd v0.23.3/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY=
github.com/btcsuite/btcd v0.23.5-0.20230125025938-be056b0a0b2f h1:UJ/S/pV25+YsK0CJRJh8RDpTgy5h1oXWjOd4fp+opvY=
github.com/btcsuite/btcd v0.23.5-0.20230125025938-be056b0a0b2f/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY=
github.com/btcsuite/btcd v0.23.5-0.20230228185050-38331963bddd h1:v2Bs8yLhwv+8XYU96OOnhZ5BEj8ZlNGownexUO0e80I=
github.com/btcsuite/btcd v0.23.5-0.20230228185050-38331963bddd/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY=
github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA=
github.com/btcsuite/btcd/btcec/v2 v2.1.1/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE=
github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE=
Expand Down
61 changes: 45 additions & 16 deletions input/script_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ type Signature interface {
// WitnessScriptHash generates a pay-to-witness-script-hash public key script
// paying to a version 0 witness program paying to the passed redeem script.
func WitnessScriptHash(witnessScript []byte) ([]byte, error) {
bldr := txscript.NewScriptBuilder()
bldr := txscript.NewScriptBuilder(
txscript.WithScriptAllocSize(P2WSHSize),
)

bldr.AddOp(txscript.OP_0)
scriptHash := sha256.Sum256(witnessScript)
Expand All @@ -47,7 +49,9 @@ func WitnessScriptHash(witnessScript []byte) ([]byte, error) {
// paying to a version 0 witness program containing the passed serialized
// public key.
func WitnessPubKeyHash(pubkey []byte) ([]byte, error) {
bldr := txscript.NewScriptBuilder()
bldr := txscript.NewScriptBuilder(
txscript.WithScriptAllocSize(P2WPKHSize),
)

bldr.AddOp(txscript.OP_0)
pkhash := btcutil.Hash160(pubkey)
Expand All @@ -58,7 +62,9 @@ func WitnessPubKeyHash(pubkey []byte) ([]byte, error) {
// GenerateP2SH generates a pay-to-script-hash public key script paying to the
// passed redeem script.
func GenerateP2SH(script []byte) ([]byte, error) {
bldr := txscript.NewScriptBuilder()
bldr := txscript.NewScriptBuilder(
txscript.WithScriptAllocSize(NestedP2WPKHSize),
)

bldr.AddOp(txscript.OP_HASH160)
scripthash := btcutil.Hash160(script)
Expand All @@ -70,7 +76,9 @@ func GenerateP2SH(script []byte) ([]byte, error) {
// GenerateP2PKH generates a pay-to-public-key-hash public key script paying to
// the passed serialized public key.
func GenerateP2PKH(pubkey []byte) ([]byte, error) {
bldr := txscript.NewScriptBuilder()
bldr := txscript.NewScriptBuilder(
txscript.WithScriptAllocSize(P2PKHSize),
)

bldr.AddOp(txscript.OP_DUP)
bldr.AddOp(txscript.OP_HASH160)
Expand All @@ -96,7 +104,8 @@ func GenerateUnknownWitness() ([]byte, error) {
// pubkeys.
func GenMultiSigScript(aPub, bPub []byte) ([]byte, error) {
if len(aPub) != 33 || len(bPub) != 33 {
return nil, fmt.Errorf("pubkey size error: compressed pubkeys only")
return nil, fmt.Errorf("pubkey size error: compressed " +
"pubkeys only")
}

// Swap to sort pubkeys if needed. Keys are sorted in lexicographical
Expand All @@ -107,7 +116,9 @@ func GenMultiSigScript(aPub, bPub []byte) ([]byte, error) {
aPub, bPub = bPub, aPub
}

bldr := txscript.NewScriptBuilder()
bldr := txscript.NewScriptBuilder(txscript.WithScriptAllocSize(
MultiSigSize,
))
bldr.AddOp(txscript.OP_2)
bldr.AddData(aPub) // Add both pubkeys (sorted).
bldr.AddData(bPub)
Expand Down Expand Up @@ -241,7 +252,9 @@ func SenderHTLCScript(senderHtlcKey, receiverHtlcKey,
revocationKey *btcec.PublicKey, paymentHash []byte,
confirmedSpend bool) ([]byte, error) {

builder := txscript.NewScriptBuilder()
builder := txscript.NewScriptBuilder(txscript.WithScriptAllocSize(
OfferedHtlcScriptSizeConfirmed,
))

// The opening operations are used to determine if this is the receiver
// of the HTLC attempting to sweep all the funds due to a contract
Expand Down Expand Up @@ -484,7 +497,9 @@ func ReceiverHTLCScript(cltvExpiry uint32, senderHtlcKey,
receiverHtlcKey, revocationKey *btcec.PublicKey,
paymentHash []byte, confirmedSpend bool) ([]byte, error) {

builder := txscript.NewScriptBuilder()
builder := txscript.NewScriptBuilder(txscript.WithScriptAllocSize(
AcceptedHtlcScriptSizeConfirmed,
))

// The opening operations are used to determine if this is the sender
// of the HTLC attempting to sweep all the funds due to a contract
Expand Down Expand Up @@ -747,7 +762,9 @@ func ReceiverHtlcSpendTimeout(signer Signer, signDesc *SignDescriptor,
func SecondLevelHtlcScript(revocationKey, delayKey *btcec.PublicKey,
csvDelay uint32) ([]byte, error) {

builder := txscript.NewScriptBuilder()
builder := txscript.NewScriptBuilder(txscript.WithScriptAllocSize(
ToLocalScriptSize,
))

// If this is the revocation clause for this script is to be executed,
// the spender will push a 1, forcing us to hit the true clause of this
Expand Down Expand Up @@ -815,7 +832,9 @@ func SecondLevelHtlcScript(revocationKey, delayKey *btcec.PublicKey,
func LeaseSecondLevelHtlcScript(revocationKey, delayKey *btcec.PublicKey,
csvDelay, cltvExpiry uint32) ([]byte, error) {

builder := txscript.NewScriptBuilder()
builder := txscript.NewScriptBuilder(txscript.WithScriptAllocSize(
ToLocalScriptSize + LeaseWitnessScriptSizeOverhead,
))

// If this is the revocation clause for this script is to be executed,
// the spender will push a 1, forcing us to hit the true clause of this
Expand Down Expand Up @@ -998,7 +1017,9 @@ func CommitScriptToSelf(csvTimeout uint32, selfKey, revokeKey *btcec.PublicKey)
// have divulged the revocation hash, allowing them to homomorphically
// derive the proper private key which corresponds to the revoke public
// key.
builder := txscript.NewScriptBuilder()
builder := txscript.NewScriptBuilder(txscript.WithScriptAllocSize(
ToLocalScriptSize,
))

builder.AddOp(txscript.OP_IF)

Expand Down Expand Up @@ -1054,7 +1075,9 @@ func LeaseCommitScriptToSelf(selfKey, revokeKey *btcec.PublicKey,
// have divulged the revocation hash, allowing them to homomorphically
// derive the proper private key which corresponds to the revoke public
// key.
builder := txscript.NewScriptBuilder()
builder := txscript.NewScriptBuilder(txscript.WithScriptAllocSize(
ToLocalScriptSize + LeaseWitnessScriptSizeOverhead,
))

builder.AddOp(txscript.OP_IF)

Expand Down Expand Up @@ -1199,7 +1222,9 @@ func CommitSpendNoDelay(signer Signer, signDesc *SignDescriptor,
// p2wkh output spendable immediately, requiring no contestation period.
func CommitScriptUnencumbered(key *btcec.PublicKey) ([]byte, error) {
// This script goes to the "other" party, and is spendable immediately.
builder := txscript.NewScriptBuilder()
builder := txscript.NewScriptBuilder(txscript.WithScriptAllocSize(
P2WPKHSize,
))
builder.AddOp(txscript.OP_0)
builder.AddData(btcutil.Hash160(key.SerializeCompressed()))

Expand All @@ -1219,7 +1244,9 @@ func CommitScriptUnencumbered(key *btcec.PublicKey) ([]byte, error) {
// <key> OP_CHECKSIGVERIFY
// 1 OP_CHECKSEQUENCEVERIFY
func CommitScriptToRemoteConfirmed(key *btcec.PublicKey) ([]byte, error) {
builder := txscript.NewScriptBuilder()
builder := txscript.NewScriptBuilder(txscript.WithScriptAllocSize(
ToRemoteConfirmedScriptSize,
))

// Only the given key can spend the output.
builder.AddData(key.SerializeCompressed())
Expand Down Expand Up @@ -1248,7 +1275,7 @@ func CommitScriptToRemoteConfirmed(key *btcec.PublicKey) ([]byte, error) {
func LeaseCommitScriptToRemoteConfirmed(key *btcec.PublicKey,
leaseExpiry uint32) ([]byte, error) {

builder := txscript.NewScriptBuilder()
builder := txscript.NewScriptBuilder(txscript.WithScriptAllocSize(45))

// Only the given key can spend the output.
builder.AddData(key.SerializeCompressed())
Expand Down Expand Up @@ -1310,7 +1337,9 @@ func CommitSpendToRemoteConfirmed(signer Signer, signDesc *SignDescriptor,
// OP_16 OP_CSV
// OP_ENDIF
func CommitScriptAnchor(key *btcec.PublicKey) ([]byte, error) {
builder := txscript.NewScriptBuilder()
builder := txscript.NewScriptBuilder(txscript.WithScriptAllocSize(
AnchorScriptSize,
))

// Spend immediately with key.
builder.AddData(key.SerializeCompressed())
Expand Down
Loading

0 comments on commit 158e93f

Please sign in to comment.