Skip to content

Commit

Permalink
release v0.5.0
Browse files Browse the repository at this point in the history
  • Loading branch information
mdb1 committed Nov 9, 2020
1 parent 1782413 commit 333256b
Show file tree
Hide file tree
Showing 458 changed files with 332,160 additions and 1,607 deletions.
50 changes: 28 additions & 22 deletions V1.go
Original file line number Diff line number Diff line change
@@ -1,65 +1,71 @@
package libwallet

import (
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
"github.com/muun/libwallet/addresses"
"github.com/pkg/errors"
)

// CreateAddressV1 returns a P2PKH MuunAddress from a publicKey for using in TransactionSchameV1
// CreateAddressV1 returns a P2PKH MuunAddress from a publicKey for use in TransactionSchemeV1
func CreateAddressV1(publicKey *HDPublicKey) (MuunAddress, error) {
pubkey, err := btcutil.NewAddressPubKey(publicKey.Raw(), publicKey.Network.network)
if err != nil {
return nil, err
}

pubkeyHash := pubkey.AddressPubKeyHash()
address := pubkeyHash.String()

return &muunAddress{address: address, version: addressV1, derivationPath: publicKey.Path}, nil
return addresses.CreateAddressV1(&publicKey.key, publicKey.Path, publicKey.Network.network)
}

func addUserSignatureInputV1(input Input, index int, tx *wire.MsgTx, privateKey *HDPrivateKey) (*wire.TxIn, error) {
type coinV1 struct {
Network *chaincfg.Params
OutPoint wire.OutPoint
KeyPath string
}

txInput := tx.TxIn[index]
func (c *coinV1) SignInput(index int, tx *wire.MsgTx, userKey *HDPrivateKey, _ *HDPublicKey) error {
userKey, err := userKey.DeriveTo(c.KeyPath)
if err != nil {
return errors.Wrapf(err, "failed to derive user key")
}

sig, err := signInputV1(input, index, tx, privateKey)
sig, err := c.signature(index, tx, userKey)
if err != nil {
return nil, errors.Wrapf(err, "failed to sign V1 input")
return errors.Wrapf(err, "failed to sign V1 input")
}

builder := txscript.NewScriptBuilder()
builder.AddData(sig)
builder.AddData(privateKey.PublicKey().Raw())
builder.AddData(userKey.PublicKey().Raw())
script, err := builder.Script()
if err != nil {
return nil, errors.Wrapf(err, "failed to generate signing script")
return errors.Wrapf(err, "failed to generate signing script")
}

txInput := tx.TxIn[index]
txInput.SignatureScript = script
return nil
}

return txInput, nil
func (c *coinV1) FullySignInput(index int, tx *wire.MsgTx, userKey, muunKey *HDPrivateKey) error {
return c.SignInput(index, tx, userKey, nil)
}

func createRedeemScriptV1(publicKey *HDPublicKey) ([]byte, error) {
func (c *coinV1) createRedeemScript(publicKey *HDPublicKey) ([]byte, error) {

userAddress, err := btcutil.NewAddressPubKey(publicKey.Raw(), publicKey.Network.network)
userAddress, err := btcutil.NewAddressPubKey(publicKey.Raw(), c.Network)
if err != nil {
return nil, errors.Wrapf(err, "failed to generate address for user")
}

return txscript.PayToAddrScript(userAddress.AddressPubKeyHash())
}

func signInputV1(input Input, index int, tx *wire.MsgTx, privateKey *HDPrivateKey) ([]byte, error) {
func (c *coinV1) signature(index int, tx *wire.MsgTx, userKey *HDPrivateKey) ([]byte, error) {

redeemScript, err := createRedeemScriptV1(privateKey.PublicKey())
redeemScript, err := c.createRedeemScript(userKey.PublicKey())
if err != nil {
return nil, errors.Wrapf(err, "failed to build reedem script for signing")
}

privKey, err := privateKey.key.ECPrivKey()
privKey, err := userKey.key.ECPrivKey()
if err != nil {
return nil, errors.Wrapf(err, "failed to produce EC priv key for signing")
}
Expand Down
90 changes: 49 additions & 41 deletions V2.go
Original file line number Diff line number Diff line change
@@ -1,67 +1,51 @@
package libwallet

import (
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcutil"
"github.com/muun/libwallet/addresses"
"github.com/pkg/errors"

"github.com/btcsuite/btcd/wire"
)

func CreateAddressV2(userKey, muunKey *HDPublicKey) (MuunAddress, error) {

script, err := createRedeemScriptV2(userKey, muunKey)
if err != nil {
return nil, errors.Wrapf(err, "failed to generate redeem script v2")
}

address, err := btcutil.NewAddressScriptHash(script, userKey.Network.network)
if err != nil {
return nil, errors.Wrapf(err, "failed to generate multisig address")
}

return &muunAddress{
address: address.String(),
version: addressV2,
derivationPath: userKey.Path,
}, nil
// TODO: check both paths match?
return addresses.CreateAddressV2(&userKey.key, &muunKey.key, userKey.Path, userKey.Network.network)
}

func createRedeemScriptV2(userKey, muunKey *HDPublicKey) ([]byte, error) {
type coinV2 struct {
Network *chaincfg.Params
OutPoint wire.OutPoint
KeyPath string
MuunSignature []byte
}

userAddress, err := btcutil.NewAddressPubKey(userKey.Raw(), userKey.Network.network)
func (c *coinV2) SignInput(index int, tx *wire.MsgTx, userKey *HDPrivateKey, muunKey *HDPublicKey) error {
userKey, err := userKey.DeriveTo(c.KeyPath)
if err != nil {
return nil, errors.Wrapf(err, "failed to generate address for user")
return errors.Wrapf(err, "failed to derive user key")
}

muunAddress, err := btcutil.NewAddressPubKey(muunKey.Raw(), muunKey.Network.network)
muunKey, err = muunKey.DeriveTo(c.KeyPath)
if err != nil {
return nil, errors.Wrapf(err, "failed to generate address for muun")
return errors.Wrapf(err, "failed to derive muun key")
}

return txscript.MultiSigScript([]*btcutil.AddressPubKey{
userAddress,
muunAddress,
}, 2)
}

func addUserSignatureInputV2(input Input, index int, tx *wire.MsgTx, privateKey *HDPrivateKey,
muunKey *HDPublicKey) (*wire.TxIn, error) {

if len(input.MuunSignature()) == 0 {
return nil, errors.Errorf("muun signature must be present")
if len(c.MuunSignature) == 0 {
return errors.Errorf("muun signature must be present")
}

txInput := tx.TxIn[index]

redeemScript, err := createRedeemScriptV2(privateKey.PublicKey(), muunKey)
redeemScript, err := createRedeemScriptV2(userKey.PublicKey(), muunKey)
if err != nil {
return nil, errors.Wrapf(err, "failed to build reedem script for signing")
return errors.Wrapf(err, "failed to build reedem script for signing")
}

sig, err := signInputV2(input, index, tx, privateKey.PublicKey(), muunKey, privateKey)
sig, err := c.signature(index, tx, userKey.PublicKey(), muunKey, userKey)
if err != nil {
return nil, err
return err
}

// This is a standard 2 of 2 multisig script
Expand All @@ -71,19 +55,39 @@ func addUserSignatureInputV2(input Input, index int, tx *wire.MsgTx, privateKey
builder := txscript.NewScriptBuilder()
builder.AddInt64(0)
builder.AddData(sig)
builder.AddData(input.MuunSignature())
builder.AddData(c.MuunSignature)
builder.AddData(redeemScript)
script, err := builder.Script()
if err != nil {
return nil, errors.Wrapf(err, "failed to generate signing script")
return errors.Wrapf(err, "failed to generate signing script")
}

txInput.SignatureScript = script

return txInput, nil
return nil
}

func signInputV2(input Input, index int, tx *wire.MsgTx, userKey, muunKey *HDPublicKey,
func (c *coinV2) FullySignInput(index int, tx *wire.MsgTx, userKey, muunKey *HDPrivateKey) error {

derivedUserKey, err := userKey.DeriveTo(c.KeyPath)
if err != nil {
return errors.Wrapf(err, "failed to derive user key")
}

derivedMuunKey, err := muunKey.DeriveTo(c.KeyPath)
if err != nil {
return errors.Wrapf(err, "failed to derive muun key")
}

muunSignature, err := c.signature(index, tx, derivedUserKey.PublicKey(), derivedMuunKey.PublicKey(), derivedMuunKey)
if err != nil {
return err
}
c.MuunSignature = muunSignature
return c.SignInput(index, tx, userKey, muunKey.PublicKey())
}

func (c *coinV2) signature(index int, tx *wire.MsgTx, userKey, muunKey *HDPublicKey,
signingKey *HDPrivateKey) ([]byte, error) {

redeemScript, err := createRedeemScriptV2(userKey, muunKey)
Expand All @@ -103,3 +107,7 @@ func signInputV2(input Input, index int, tx *wire.MsgTx, userKey, muunKey *HDPub

return sig, nil
}

func createRedeemScriptV2(userKey, muunKey *HDPublicKey) ([]byte, error) {
return addresses.CreateRedeemScriptV2(&userKey.key, &muunKey.key, userKey.Network.network)
}
84 changes: 52 additions & 32 deletions V3.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,70 +2,89 @@ package libwallet

import (
"github.com/btcsuite/btcutil"
"github.com/muun/libwallet/addresses"

"github.com/pkg/errors"

"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/wire"
)

func CreateAddressV3(userKey, muunKey *HDPublicKey) (MuunAddress, error) {
return addresses.CreateAddressV3(&userKey.key, &muunKey.key, userKey.Path, userKey.Network.network)
}

redeemScript, err := createRedeemScriptV3(userKey, muunKey)
type coinV3 struct {
Network *chaincfg.Params
OutPoint wire.OutPoint
KeyPath string
Amount btcutil.Amount
MuunSignature []byte
}

func (c *coinV3) SignInput(index int, tx *wire.MsgTx, userKey *HDPrivateKey, muunKey *HDPublicKey) error {

userKey, err := userKey.DeriveTo(c.KeyPath)
if err != nil {
return nil, err
return errors.Wrapf(err, "failed to derive user key")
}

address, err := btcutil.NewAddressScriptHash(redeemScript, userKey.Network.network)
muunKey, err = muunKey.DeriveTo(c.KeyPath)
if err != nil {
return nil, err
return errors.Wrapf(err, "failed to derive muun key")
}

return &muunAddress{
address: address.EncodeAddress(),
version: addressV3,
derivationPath: userKey.Path,
}, nil
}
if len(c.MuunSignature) == 0 {
return errors.Errorf("muun signature must be present")
}

func createRedeemScriptV3(userKey, muunKey *HDPublicKey) ([]byte, error) {
witnessScript, err := createWitnessScriptV3(userKey, muunKey)
witnessScript, err := createWitnessScriptV3(userKey.PublicKey(), muunKey)
if err != nil {
return nil, errors.Wrapf(err, "failed to generate redeem script v3")
return err
}

return createNonNativeSegwitRedeemScript(witnessScript)
}
sig, err := c.signature(index, tx, userKey.PublicKey(), muunKey, userKey)
if err != nil {
return err
}

func createWitnessScriptV3(userKey, muunKey *HDPublicKey) ([]byte, error) {
// createRedeemScriptV2 creates a valid script for both V2 and V3 schemes
return createRedeemScriptV2(userKey, muunKey)
zeroByteArray := []byte{}

txInput := tx.TxIn[index]
txInput.Witness = wire.TxWitness{zeroByteArray, sig, c.MuunSignature, witnessScript}

return nil
}

func addUserSignatureInputV3(input Input, index int, tx *wire.MsgTx, privateKey *HDPrivateKey, muunKey *HDPublicKey) (*wire.TxIn, error) {
func (c *coinV3) FullySignInput(index int, tx *wire.MsgTx, userKey, muunKey *HDPrivateKey) error {

if len(input.MuunSignature()) == 0 {
return nil, errors.Errorf("muun signature must be present")
derivedUserKey, err := userKey.DeriveTo(c.KeyPath)
if err != nil {
return errors.Wrapf(err, "failed to derive user key")
}

witnessScript, err := createWitnessScriptV3(privateKey.PublicKey(), muunKey)
derivedMuunKey, err := muunKey.DeriveTo(c.KeyPath)
if err != nil {
return nil, err
return errors.Wrapf(err, "failed to derive muun key")
}

sig, err := signInputV3(input, index, tx, privateKey.PublicKey(), muunKey, privateKey)
muunSignature, err := c.signature(index, tx, derivedUserKey.PublicKey(), derivedMuunKey.PublicKey(), derivedMuunKey)
if err != nil {
return nil, err
return err
}
c.MuunSignature = muunSignature
return c.SignInput(index, tx, userKey, muunKey.PublicKey())
}

zeroByteArray := []byte{}

txInput := tx.TxIn[index]
txInput.Witness = wire.TxWitness{zeroByteArray, sig, input.MuunSignature(), witnessScript}
func createRedeemScriptV3(userKey, muunKey *HDPublicKey) ([]byte, error) {
return addresses.CreateRedeemScriptV3(&userKey.key, &muunKey.key, userKey.Network.network)
}

return txInput, nil
func createWitnessScriptV3(userKey, muunKey *HDPublicKey) ([]byte, error) {
return addresses.CreateWitnessScriptV3(&userKey.key, &muunKey.key, userKey.Network.network)
}

func signInputV3(input Input, index int, tx *wire.MsgTx, userKey *HDPublicKey, muunKey *HDPublicKey,
func (c *coinV3) signature(index int, tx *wire.MsgTx, userKey *HDPublicKey, muunKey *HDPublicKey,
signingKey *HDPrivateKey) ([]byte, error) {

witnessScript, err := createWitnessScriptV3(userKey, muunKey)
Expand All @@ -78,5 +97,6 @@ func signInputV3(input Input, index int, tx *wire.MsgTx, userKey *HDPublicKey, m
return nil, errors.Wrapf(err, "failed to build reedem script for signing")
}

return signNonNativeSegwitInput(input, index, tx, signingKey, redeemScript, witnessScript)
return signNonNativeSegwitInput(
index, tx, signingKey, redeemScript, witnessScript, c.Amount)
}
Loading

0 comments on commit 333256b

Please sign in to comment.