2015-12-21 02:10:24 +03:00
|
|
|
package lnwallet
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"github.com/btcsuite/btcd/txscript"
|
|
|
|
"github.com/btcsuite/btcd/wire"
|
|
|
|
"github.com/btcsuite/btcutil"
|
|
|
|
)
|
|
|
|
|
|
|
|
// scriptHashPkScript...
|
|
|
|
func scriptHashPkScript(scriptBytes []byte) ([]byte, error) {
|
|
|
|
bldr := txscript.NewScriptBuilder()
|
|
|
|
bldr.AddOp(txscript.OP_HASH160)
|
|
|
|
bldr.AddData(btcutil.Hash160(scriptBytes))
|
|
|
|
bldr.AddOp(txscript.OP_EQUAL)
|
|
|
|
return bldr.Script()
|
|
|
|
}
|
|
|
|
|
|
|
|
// getFundingPkScript generates the non-p2sh'd multisig script for 2 of 2
|
|
|
|
// pubkeys.
|
|
|
|
func genFundingPkScript(aPub, bPub []byte) ([]byte, error) {
|
|
|
|
if len(aPub) != 33 || len(bPub) != 33 {
|
|
|
|
return nil, fmt.Errorf("Pubkey size error. Compressed pubkeys only")
|
|
|
|
}
|
|
|
|
|
|
|
|
if bytes.Compare(aPub, bPub) == -1 { // swap to sort pubkeys if needed
|
|
|
|
aPub, bPub = bPub, aPub
|
|
|
|
}
|
|
|
|
|
|
|
|
bldr := txscript.NewScriptBuilder()
|
|
|
|
// Require 2 signatures, so from both of the pubkeys
|
|
|
|
bldr.AddOp(txscript.OP_2)
|
|
|
|
// add both pubkeys (sorted)
|
|
|
|
bldr.AddData(aPub)
|
|
|
|
bldr.AddData(bPub)
|
|
|
|
// 2 keys total. In case that wasn't obvious.
|
|
|
|
bldr.AddOp(txscript.OP_2)
|
|
|
|
// Good ol OP_CHECKMULTISIG. Don't forget the zero!
|
|
|
|
bldr.AddOp(txscript.OP_CHECKMULTISIG)
|
|
|
|
// get byte slice
|
|
|
|
return bldr.Script()
|
|
|
|
}
|
|
|
|
|
|
|
|
// fundMultiSigOut creates a TxOut for the funding transaction.
|
|
|
|
// Give it the two pubkeys and it'll give you the p2sh'd txout.
|
|
|
|
// You don't have to remember the p2sh preimage, as long as you remember the
|
|
|
|
// pubkeys involved.
|
|
|
|
func fundMultiSigOut(aPub, bPub []byte, amt int64) ([]byte, *wire.TxOut, error) {
|
|
|
|
if amt < 0 {
|
|
|
|
return nil, nil, fmt.Errorf("Can't create FundTx script with negative coins")
|
|
|
|
}
|
|
|
|
|
|
|
|
// p2shify
|
|
|
|
redeemScript, err := genFundingPkScript(aPub, bPub)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
pkScript, err := scriptHashPkScript(redeemScript)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return redeemScript, wire.NewTxOut(amt, pkScript), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// the scriptsig to put on a P2SH input
|
|
|
|
func spendMultiSig(redeemScript, sigA, sigB []byte) ([]byte, error) {
|
|
|
|
bldr := txscript.NewScriptBuilder()
|
|
|
|
|
|
|
|
// add a 0 for some multisig fun
|
|
|
|
bldr.AddOp(txscript.OP_0)
|
|
|
|
|
|
|
|
// add sigA
|
|
|
|
bldr.AddData(sigA)
|
|
|
|
// add sigB
|
|
|
|
bldr.AddData(sigB)
|
|
|
|
|
|
|
|
// preimage goes on AT THE ENDDDD
|
|
|
|
bldr.AddData(redeemScript)
|
|
|
|
|
|
|
|
// that's all, get bytes
|
|
|
|
return bldr.Script()
|
|
|
|
}
|
2015-12-21 06:47:29 +03:00
|
|
|
|
|
|
|
// findScriptOutputIndex...
|
|
|
|
// only finds first matchin, assumes unique pkScripts
|
|
|
|
func findScriptOutputIndex(tx *wire.MsgTx, script []byte) (bool, uint32) {
|
|
|
|
found := false
|
|
|
|
index := uint32(0)
|
|
|
|
for i, txOut := range tx.TxOut {
|
|
|
|
if bytes.Equal(txOut.PkScript, script) {
|
|
|
|
found = true
|
|
|
|
index = uint32(i)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return found, index
|
|
|
|
}
|