muun-recovery/recovery_tool.go

138 lines
2.7 KiB
Go
Raw Normal View History

2019-10-01 11:22:30 -04:00
package main
import (
"bytes"
2021-03-17 14:28:04 -04:00
"encoding/hex"
2019-10-01 11:22:30 -04:00
2021-03-17 14:28:04 -04:00
"github.com/btcsuite/btcd/chaincfg/chainhash"
2019-10-01 11:22:30 -04:00
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
"github.com/muun/libwallet"
2021-03-17 14:28:04 -04:00
"github.com/muun/recovery/scanner"
2019-10-01 11:22:30 -04:00
)
2021-03-17 14:28:04 -04:00
func buildSweepTx(utxos []*scanner.Utxo, sweepAddress btcutil.Address, fee int64) ([]byte, error) {
2019-10-01 11:22:30 -04:00
tx := wire.NewMsgTx(2)
value := int64(0)
for _, utxo := range utxos {
2021-03-17 14:28:04 -04:00
chainHash, err := chainhash.NewHashFromStr(utxo.TxID)
if err != nil {
return nil, err
}
outpoint := wire.OutPoint{
Hash: *chainHash,
Index: uint32(utxo.OutputIndex),
}
tx.AddTxIn(wire.NewTxIn(&outpoint, []byte{}, [][]byte{}))
value += utxo.Amount
2019-10-01 11:22:30 -04:00
}
value -= fee
script, err := txscript.PayToAddrScript(sweepAddress)
if err != nil {
2021-03-17 14:28:04 -04:00
return nil, err
2019-10-01 11:22:30 -04:00
}
tx.AddTxOut(wire.NewTxOut(value, script))
writer := &bytes.Buffer{}
err = tx.Serialize(writer)
if err != nil {
2021-03-17 14:28:04 -04:00
return nil, err
2019-10-01 11:22:30 -04:00
}
if fee != 0 {
readConfirmation(value, fee, sweepAddress.String())
}
2021-03-17 14:28:04 -04:00
return writer.Bytes(), nil
2019-10-01 11:22:30 -04:00
}
2021-03-17 14:28:04 -04:00
func buildSignedTx(utxos []*scanner.Utxo, sweepTx []byte, userKey *libwallet.HDPrivateKey,
2019-10-01 11:22:30 -04:00
muunKey *libwallet.HDPrivateKey) (*wire.MsgTx, error) {
2020-11-09 08:05:29 -05:00
inputList := &libwallet.InputList{}
for _, utxo := range utxos {
inputList.Add(&input{
2019-10-01 11:22:30 -04:00
utxo,
[]byte{},
2020-11-09 08:05:29 -05:00
})
}
2019-10-01 11:22:30 -04:00
2020-11-09 08:05:29 -05:00
pstx, err := libwallet.NewPartiallySignedTransaction(inputList, sweepTx)
if err != nil {
2021-03-17 14:28:04 -04:00
return nil, err
2019-10-01 11:22:30 -04:00
}
2020-11-09 08:05:29 -05:00
signedTx, err := pstx.FullySign(userKey, muunKey)
2019-10-01 11:22:30 -04:00
if err != nil {
return nil, err
}
wireTx := wire.NewMsgTx(0)
wireTx.BtcDecode(bytes.NewReader(signedTx.Bytes), 0, wire.WitnessEncoding)
return wireTx, nil
}
2021-03-17 14:28:04 -04:00
// input is a minimal type that implements libwallet.Input
2019-10-01 11:22:30 -04:00
type input struct {
2021-03-17 14:28:04 -04:00
utxo *scanner.Utxo
2019-10-01 11:22:30 -04:00
muunSignature []byte
}
func (i *input) OutPoint() libwallet.Outpoint {
2021-03-17 14:28:04 -04:00
return &outpoint{utxo: i.utxo}
2019-10-01 11:22:30 -04:00
}
func (i *input) Address() libwallet.MuunAddress {
2021-03-17 14:28:04 -04:00
return i.utxo.Address
2019-10-01 11:22:30 -04:00
}
func (i *input) UserSignature() []byte {
return []byte{}
}
func (i *input) MuunSignature() []byte {
return i.muunSignature
}
2019-11-28 18:13:09 -05:00
func (i *input) SubmarineSwapV1() libwallet.InputSubmarineSwapV1 {
return nil
}
func (i *input) SubmarineSwapV2() libwallet.InputSubmarineSwapV2 {
2019-10-01 11:22:30 -04:00
return nil
}
2020-11-09 08:05:29 -05:00
func (i *input) IncomingSwap() libwallet.InputIncomingSwap {
return nil
}
2021-03-17 14:28:04 -04:00
// outpoint is a minimal type that implements libwallet.Outpoint
2019-10-01 11:22:30 -04:00
type outpoint struct {
2021-03-17 14:28:04 -04:00
utxo *scanner.Utxo
2019-10-01 11:22:30 -04:00
}
func (o *outpoint) TxId() []byte {
2021-03-17 14:28:04 -04:00
raw, err := hex.DecodeString(o.utxo.TxID)
if err != nil {
panic(err) // we wrote this hex value ourselves, no input from anywhere else
}
return raw
2019-10-01 11:22:30 -04:00
}
func (o *outpoint) Index() int {
2021-03-17 14:28:04 -04:00
return o.utxo.OutputIndex
2019-10-01 11:22:30 -04:00
}
func (o *outpoint) Amount() int64 {
2021-03-17 14:28:04 -04:00
return o.utxo.Amount
2019-10-01 11:22:30 -04:00
}