utils: remove utils package in favor of new swap package

This commit is contained in:
Olaoluwa Osuntokun 2019-03-06 18:20:51 -08:00
parent cdcb9f8345
commit f552bc06b1
No known key found for this signature in database
GPG key ID: CE58F7F8E20FD9A2
8 changed files with 147 additions and 174 deletions

View file

@ -1,9 +0,0 @@
package utils
var (
// SwapKeyFamily is the key family used to generate keys that allow
// spending of the htlc.
//
// TODO(joost): decide on actual value
SwapKeyFamily = int32(99)
)

View file

@ -1,180 +0,0 @@
package utils
import (
"bytes"
"errors"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/lntypes"
)
// Htlc contains relevant htlc information from the receiver perspective.
type Htlc struct {
Script []byte
ScriptHash []byte
Hash lntypes.Hash
MaxSuccessWitnessSize int
MaxTimeoutWitnessSize int
}
var (
quoteKey [33]byte
quoteHash lntypes.Hash
// QuoteHtlc is a template script just used for fee estimation. It uses
// the maximum value for cltv expiry to get the maximum (worst case)
// script size.
QuoteHtlc, _ = NewHtlc(
^int32(0), quoteKey, quoteKey, quoteHash,
)
)
// NewHtlc returns a new instance.
func NewHtlc(cltvExpiry int32, senderKey, receiverKey [33]byte,
hash lntypes.Hash) (*Htlc, error) {
script, err := swapHTLCScript(
cltvExpiry, senderKey, receiverKey, hash,
)
if err != nil {
return nil, err
}
scriptHash, err := input.WitnessScriptHash(script)
if err != nil {
return nil, err
}
// Calculate maximum success witness size
//
// - number_of_witness_elements: 1 byte
// - receiver_sig_length: 1 byte
// - receiver_sig: 73 bytes
// - preimage_length: 1 byte
// - preimage: 33 bytes
// - witness_script_length: 1 byte
// - witness_script: len(script) bytes
maxSuccessWitnessSize := 1 + 1 + 73 + 1 + 33 + 1 + len(script)
// Calculate maximum timeout witness size
//
// - number_of_witness_elements: 1 byte
// - sender_sig_length: 1 byte
// - sender_sig: 73 bytes
// - zero_length: 1 byte
// - zero: 1 byte
// - witness_script_length: 1 byte
// - witness_script: len(script) bytes
maxTimeoutWitnessSize := 1 + 1 + 73 + 1 + 1 + 1 + len(script)
return &Htlc{
Hash: hash,
Script: script,
ScriptHash: scriptHash,
MaxSuccessWitnessSize: maxSuccessWitnessSize,
MaxTimeoutWitnessSize: maxTimeoutWitnessSize,
}, nil
}
// SwapHTLCScript returns the on-chain HTLC witness script.
//
// OP_SIZE 32 OP_EQUAL
// OP_IF
// OP_HASH160 <ripemd160(swap_hash)> OP_EQUALVERIFY
// <recvr key>
// OP_ELSE
// OP_DROP
// <cltv timeout> OP_CHECKLOCKTIMEVERIFY OP_DROP
// <sender key>
// OP_ENDIF
// OP_CHECKSIG
func swapHTLCScript(cltvExpiry int32, senderHtlcKey,
receiverHtlcKey [33]byte, swapHash lntypes.Hash) ([]byte, error) {
builder := txscript.NewScriptBuilder()
builder.AddOp(txscript.OP_SIZE)
builder.AddInt64(32)
builder.AddOp(txscript.OP_EQUAL)
builder.AddOp(txscript.OP_IF)
builder.AddOp(txscript.OP_HASH160)
builder.AddData(input.Ripemd160H(swapHash[:]))
builder.AddOp(txscript.OP_EQUALVERIFY)
builder.AddData(receiverHtlcKey[:])
builder.AddOp(txscript.OP_ELSE)
builder.AddOp(txscript.OP_DROP)
builder.AddInt64(int64(cltvExpiry))
builder.AddOp(txscript.OP_CHECKLOCKTIMEVERIFY)
builder.AddOp(txscript.OP_DROP)
builder.AddData(senderHtlcKey[:])
builder.AddOp(txscript.OP_ENDIF)
builder.AddOp(txscript.OP_CHECKSIG)
return builder.Script()
}
// Address returns the p2wsh address of the htlc.
func (h *Htlc) Address(chainParams *chaincfg.Params) (
btcutil.Address, error) {
// Skip OP_0 and data length.
return btcutil.NewAddressWitnessScriptHash(
h.ScriptHash[2:],
chainParams,
)
}
// GenSuccessWitness returns the success script to spend this htlc with the
// preimage.
func (h *Htlc) GenSuccessWitness(receiverSig []byte,
preimage lntypes.Preimage) (wire.TxWitness, error) {
if h.Hash != preimage.Hash() {
return nil, errors.New("preimage doesn't match hash")
}
witnessStack := make(wire.TxWitness, 3)
witnessStack[0] = append(receiverSig, byte(txscript.SigHashAll))
witnessStack[1] = preimage[:]
witnessStack[2] = h.Script
return witnessStack, nil
}
// IsSuccessWitness checks whether the given stack is valid for redeeming the
// htlc.
func (h *Htlc) IsSuccessWitness(witness wire.TxWitness) bool {
if len(witness) != 3 {
return false
}
isTimeoutTx := bytes.Equal([]byte{0}, witness[1])
return !isTimeoutTx
}
// GenTimeoutWitness returns the timeout script to spend this htlc after
// timeout.
func (h *Htlc) GenTimeoutWitness(senderSig []byte) (wire.TxWitness, error) {
witnessStack := make(wire.TxWitness, 3)
witnessStack[0] = append(senderSig, byte(txscript.SigHashAll))
witnessStack[1] = []byte{0}
witnessStack[2] = h.Script
return witnessStack, nil
}

View file

@ -1,41 +0,0 @@
package utils
import (
"fmt"
"github.com/btcsuite/btclog"
"github.com/lightningnetwork/lnd/lntypes"
)
// SwapLog logs with a short swap hash prefix.
type SwapLog struct {
Logger btclog.Logger
Hash lntypes.Hash
}
// Infof formats message according to format specifier and writes to
// log with LevelInfo.
func (s *SwapLog) Infof(format string, params ...interface{}) {
s.Logger.Infof(
fmt.Sprintf("%v %s", ShortHash(&s.Hash), format),
params...,
)
}
// Warnf formats message according to format specifier and writes to
// to log with LevelError.
func (s *SwapLog) Warnf(format string, params ...interface{}) {
s.Logger.Warnf(
fmt.Sprintf("%v %s", ShortHash(&s.Hash), format),
params...,
)
}
// Errorf formats message according to format specifier and writes to
// to log with LevelError.
func (s *SwapLog) Errorf(format string, params ...interface{}) {
s.Logger.Errorf(
fmt.Sprintf("%v %s", ShortHash(&s.Hash), format),
params...,
)
}

View file

@ -1,123 +0,0 @@
package utils
import (
"bytes"
"errors"
"fmt"
"os"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcutil"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/zpay32"
"github.com/btcsuite/btcd/wire"
)
const (
// FeeRateTotalParts defines the granularity of the fee rate.
FeeRateTotalParts = 1e6
)
// ShortHash returns a shortened version of the hash suitable for use in
// logging.
func ShortHash(hash *lntypes.Hash) string {
return hash.String()[:6]
}
// EncodeTx encodes a tx to raw bytes.
func EncodeTx(tx *wire.MsgTx) ([]byte, error) {
var buffer bytes.Buffer
err := tx.BtcEncode(&buffer, 0, wire.WitnessEncoding)
if err != nil {
return nil, err
}
rawTx := buffer.Bytes()
return rawTx, nil
}
// DecodeTx decodes raw tx bytes.
func DecodeTx(rawTx []byte) (*wire.MsgTx, error) {
tx := wire.MsgTx{}
r := bytes.NewReader(rawTx)
err := tx.BtcDecode(r, 0, wire.WitnessEncoding)
if err != nil {
return nil, err
}
return &tx, nil
}
// GetInvoiceAmt gets the invoice amount. It requires an amount to be specified.
func GetInvoiceAmt(params *chaincfg.Params,
payReq string) (btcutil.Amount, error) {
swapPayReq, err := zpay32.Decode(
payReq, params,
)
if err != nil {
return 0, err
}
if swapPayReq.MilliSat == nil {
return 0, errors.New("no amount in invoice")
}
return swapPayReq.MilliSat.ToSatoshis(), nil
}
// FileExists returns true if the file exists, and false otherwise.
func FileExists(path string) bool {
if _, err := os.Stat(path); err != nil {
if os.IsNotExist(err) {
return false
}
}
return true
}
// ChainParamsFromNetwork returns chain parameters based on a network name.
func ChainParamsFromNetwork(network string) (*chaincfg.Params, error) {
switch network {
case "mainnet":
return &chaincfg.MainNetParams, nil
case "testnet":
return &chaincfg.TestNet3Params, nil
case "regtest":
return &chaincfg.RegressionNetParams, nil
case "simnet":
return &chaincfg.SimNetParams, nil
default:
return nil, errors.New("unknown network")
}
}
// GetScriptOutput locates the given script in the outputs of a transaction and
// returns its outpoint and value.
func GetScriptOutput(htlcTx *wire.MsgTx, scriptHash []byte) (
*wire.OutPoint, btcutil.Amount, error) {
for idx, output := range htlcTx.TxOut {
if bytes.Equal(output.PkScript, scriptHash) {
return &wire.OutPoint{
Hash: htlcTx.TxHash(),
Index: uint32(idx),
}, btcutil.Amount(output.Value), nil
}
}
return nil, 0, fmt.Errorf("cannot determine outpoint")
}
// CalcFee returns the swap fee for a given swap amount.
func CalcFee(amount, feeBase btcutil.Amount, feeRate int64) btcutil.Amount {
return feeBase + amount*btcutil.Amount(feeRate)/
btcutil.Amount(FeeRateTotalParts)
}
// FeeRateAsPercentage converts a feerate to a percentage.
func FeeRateAsPercentage(feeRate int64) float64 {
return float64(feeRate) / (FeeRateTotalParts / 100)
}