2019-12-11 18:43:47 -08:00
|
|
|
package clmscript
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bytes"
|
2020-01-23 16:04:40 -08:00
|
|
|
"crypto/sha256"
|
2019-12-11 18:43:47 -08:00
|
|
|
|
2020-01-23 16:04:33 -08:00
|
|
|
"github.com/btcsuite/btcd/btcec"
|
2019-12-11 18:43:47 -08:00
|
|
|
"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
|
|
|
|
|
)
|
|
|
|
|
|
2020-01-23 16:04:40 -08:00
|
|
|
// 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)
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-11 18:43:47 -08:00
|
|
|
// AccountScript returns the witness script of an account on-chain.
|
|
|
|
|
//
|
2020-01-24 15:28:23 -08:00
|
|
|
// <trader_key> OP_CHECKSIGVERIFY
|
|
|
|
|
// <auctioneer_key> OP_CHECKSIG OP_IFDUP OP_NOTIF
|
|
|
|
|
// <account_expiry> OP_CHECKLOCKTIMEVERIFY
|
2019-12-11 18:43:47 -08:00
|
|
|
// OP_ENDIF
|
2020-01-23 16:04:40 -08:00
|
|
|
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)
|
|
|
|
|
|
2019-12-11 18:43:47 -08:00
|
|
|
builder := txscript.NewScriptBuilder()
|
|
|
|
|
|
2020-01-23 16:04:40 -08:00
|
|
|
builder.AddData(tweakedTraderKey.SerializeCompressed())
|
2020-01-24 15:28:23 -08:00
|
|
|
builder.AddOp(txscript.OP_CHECKSIGVERIFY)
|
2019-12-11 18:43:47 -08:00
|
|
|
|
2020-01-23 16:04:40 -08:00
|
|
|
builder.AddData(tweakedAuctioneerKey.SerializeCompressed())
|
2020-01-24 15:28:23 -08:00
|
|
|
builder.AddOp(txscript.OP_CHECKSIG)
|
2019-12-11 18:43:47 -08:00
|
|
|
|
2020-01-24 15:28:23 -08:00
|
|
|
builder.AddOp(txscript.OP_IFDUP)
|
|
|
|
|
builder.AddOp(txscript.OP_NOTIF)
|
|
|
|
|
builder.AddInt64(int64(expiry))
|
|
|
|
|
builder.AddOp(txscript.OP_CHECKLOCKTIMEVERIFY)
|
2019-12-11 18:43:47 -08:00
|
|
|
builder.AddOp(txscript.OP_ENDIF)
|
|
|
|
|
|
|
|
|
|
script, err := builder.Script()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return input.WitnessScriptHash(script)
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-23 16:04:38 -08:00
|
|
|
// 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(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-11 18:43:47 -08:00
|
|
|
// 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
|
|
|
|
|
}
|