Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

input: reduce memory allocation for ScriptBuilder #7464

Merged
merged 5 commits into from
Apr 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -40,7 +40,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