mirror of
https://github.com/lightninglabs/pool.git
synced 2026-08-13 12:33:04 +02:00
The new construction saves about 35 bytes over the existing one. The reduction in size comes from only encoding each public key (the trader's and auctioneer's) once and not using the extra opcodes for OP_CHECKMULTISIG.
92 lines
2.7 KiB
Go
92 lines
2.7 KiB
Go
package clmscript
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/sha256"
|
|
|
|
"github.com/btcsuite/btcd/btcec"
|
|
"github.com/btcsuite/btcd/txscript"
|
|
"github.com/btcsuite/btcd/wire"
|
|
"github.com/lightningnetwork/lnd/input"
|
|
"github.com/lightningnetwork/lnd/keychain"
|
|
)
|
|
|
|
const (
|
|
// AccountKeyFamily is the key family used to derive keys which will be
|
|
// used in the 2 of 2 multi-sig construction of a CLM account.
|
|
//
|
|
// TODO(wilmer): decide on actual value.
|
|
AccountKeyFamily keychain.KeyFamily = 220
|
|
)
|
|
|
|
// TraderKeyTweak computes the tweak based on the current per-batch key and
|
|
// shared secret that should be applied to an account's trader key. The tweak is
|
|
// computed as the following:
|
|
//
|
|
// tweak = sha256(batchKey || secret || traderKey)
|
|
func TraderKeyTweak(batchKey *btcec.PublicKey, secret [32]byte,
|
|
traderKey *btcec.PublicKey) []byte {
|
|
|
|
h := sha256.New()
|
|
_, _ = h.Write(batchKey.SerializeCompressed())
|
|
_, _ = h.Write(secret[:])
|
|
_, _ = h.Write(traderKey.SerializeCompressed())
|
|
return h.Sum(nil)
|
|
}
|
|
|
|
// AccountScript returns the witness script of an account on-chain.
|
|
//
|
|
// <trader_key> OP_CHECKSIGVERIFY
|
|
// <auctioneer_key> OP_CHECKSIG OP_IFDUP OP_NOTIF
|
|
// <account_expiry> OP_CHECKLOCKTIMEVERIFY
|
|
// OP_ENDIF
|
|
func AccountScript(expiry uint32, traderKey, auctioneerKey,
|
|
batchKey *btcec.PublicKey, secret [32]byte) ([]byte, error) {
|
|
|
|
traderKeyTweak := TraderKeyTweak(batchKey, secret, traderKey)
|
|
tweakedTraderKey := input.TweakPubKeyWithTweak(traderKey, traderKeyTweak)
|
|
tweakedAuctioneerKey := input.TweakPubKey(auctioneerKey, tweakedTraderKey)
|
|
|
|
builder := txscript.NewScriptBuilder()
|
|
|
|
builder.AddData(tweakedTraderKey.SerializeCompressed())
|
|
builder.AddOp(txscript.OP_CHECKSIGVERIFY)
|
|
|
|
builder.AddData(tweakedAuctioneerKey.SerializeCompressed())
|
|
builder.AddOp(txscript.OP_CHECKSIG)
|
|
|
|
builder.AddOp(txscript.OP_IFDUP)
|
|
builder.AddOp(txscript.OP_NOTIF)
|
|
builder.AddInt64(int64(expiry))
|
|
builder.AddOp(txscript.OP_CHECKLOCKTIMEVERIFY)
|
|
builder.AddOp(txscript.OP_ENDIF)
|
|
|
|
script, err := builder.Script()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return input.WitnessScriptHash(script)
|
|
}
|
|
|
|
// IncrementKey increments the given key by the backing curve's base point.
|
|
func IncrementKey(key *btcec.PublicKey) *btcec.PublicKey {
|
|
curveParams := key.Curve.Params()
|
|
newX, newY := key.Curve.Add(key.X, key.Y, curveParams.Gx, curveParams.Gy)
|
|
return &btcec.PublicKey{
|
|
X: newX,
|
|
Y: newY,
|
|
Curve: btcec.S256(),
|
|
}
|
|
}
|
|
|
|
// LocateOutputScript determines whether a transaction includes an output with a
|
|
// specific script. If it does, the output index is returned.
|
|
func LocateOutputScript(tx *wire.MsgTx, script []byte) (uint32, bool) {
|
|
for i, txOut := range tx.TxOut {
|
|
if !bytes.Equal(txOut.PkScript, script) {
|
|
continue
|
|
}
|
|
return uint32(i), true
|
|
}
|
|
return 0, false
|
|
}
|