From 3d67bf23b0c1ea265bae4e23ad083022f8eb4a35 Mon Sep 17 00:00:00 2001 From: sekulicd Date: Wed, 20 May 2020 13:41:54 +0200 Subject: [PATCH 1/2] added factory method FromPublicKeys for creating multiscript payment --- payment/payment.go | 36 +++++++++++++++++++++++++++++++++++- payment/payment_test.go | 29 ++++++++++++++++++++++++----- 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/payment/payment.go b/payment/payment.go index 6fe6fe1..5ae1450 100644 --- a/payment/payment.go +++ b/payment/payment.go @@ -3,7 +3,9 @@ package payment import ( "crypto/sha256" "errors" + "fmt" "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/txscript" "github.com/vulpemventures/go-elements/address" "github.com/vulpemventures/go-elements/network" "golang.org/x/crypto/ripemd160" @@ -11,7 +13,8 @@ import ( ) const ( - Op0 = 0x00 + Op0 = 0x00 // 0 + OpCheckMultiSig = 0xae // 174 ) // Payment defines the structure that holds the information different addresses @@ -45,6 +48,37 @@ func FromPublicKey(pubkey *btcec.PublicKey, net *network.Network) *Payment { return &Payment{tmpNet, pubkey, pkHash, nil, nil, script, witnessHash[:]} } +// FromPublicKeys creates a multi-signature Payment struct from list of public key's +func FromPublicKeys(pubkeys []*btcec.PublicKey, numOfPksRequired int, net *network.Network) (*Payment, error) { + if len(pubkeys) < numOfPksRequired { + errorMsg := fmt.Sprintf("unable to generate multisig script with "+ + "%d required signatures when there are only %d public "+ + "keys available", numOfPksRequired, len(pubkeys)) + return nil, errors.New(errorMsg) + } + + var tmpNet *network.Network + if net == nil { + tmpNet = &network.Liquid + } else { + tmpNet = net + } + + builder := txscript.NewScriptBuilder().AddInt64(int64(numOfPksRequired)) + for _, key := range pubkeys { + builder.AddData(key.SerializeCompressed()) + } + builder.AddInt64(int64(len(pubkeys))) + builder.AddOp(OpCheckMultiSig) + + multiSigScript, err := builder.Script() + if err != nil { + return nil, err + } + + return FromScript(multiSigScript, tmpNet) +} + // FromPayment creates a Payment struct from a another Payment func FromPayment(payment *Payment) (*Payment, error) { if payment.Script == nil || len(payment.Script) == 0 { diff --git a/payment/payment_test.go b/payment/payment_test.go index 9457343..702ff41 100644 --- a/payment/payment_test.go +++ b/payment/payment_test.go @@ -8,12 +8,16 @@ import ( "testing" ) -const privKeyHex = "1cc080a4cd371eafcad489a29664af6a7276b362fe783443ce036552482b971d" +const ( + privKeyHex1 = "1cc080a4cd371eafcad489a29664af6a7276b362fe783443ce036552482b971d" + privKeyHex2 = "4d6718d4a02f774e752faa97e2c3b70db6b9d9ed5bd2fcecb093bd650f449a51" +) -var privateKeyBytes, _ = hex.DecodeString(privKeyHex) +var privateKeyBytes1, _ = hex.DecodeString(privKeyHex1) +var privateKeyBytes2, _ = hex.DecodeString(privKeyHex2) func TestLegacyAddress(t *testing.T) { - _, publicKey := btcec.PrivKeyFromBytes(btcec.S256(), privateKeyBytes) + _, publicKey := btcec.PrivKeyFromBytes(btcec.S256(), privateKeyBytes1) pay := payment.FromPublicKey(publicKey, &network.Regtest) if pay.PubKeyHash() != "2dxEMfPLNa6rZRAfPe7wNWoaUptyBzQ2Zva" { @@ -22,7 +26,7 @@ func TestLegacyAddress(t *testing.T) { } func TestSegwitAddress(t *testing.T) { - _, publicKey := btcec.PrivKeyFromBytes(btcec.S256(), privateKeyBytes) + _, publicKey := btcec.PrivKeyFromBytes(btcec.S256(), privateKeyBytes1) pay := payment.FromPublicKey(publicKey, &network.Regtest) p2pkh, err := pay.WitnessPubKeyHash() @@ -35,7 +39,7 @@ func TestSegwitAddress(t *testing.T) { } func TestScriptHash(t *testing.T) { - _, publicKey := btcec.PrivKeyFromBytes(btcec.S256(), privateKeyBytes) + _, publicKey := btcec.PrivKeyFromBytes(btcec.S256(), privateKeyBytes1) p2wpkh := payment.FromPublicKey(publicKey, &network.Regtest) pay, err := payment.FromPayment(p2wpkh) p2sh, err := pay.ScriptHash() @@ -72,3 +76,18 @@ func TestP2WSH(t *testing.T) { t.Errorf("TestSegwitAddress: error when encoding segwit") } } + +func TestFromPublicKeys(t *testing.T) { + _, publicKey1 := btcec.PrivKeyFromBytes(btcec.S256(), privateKeyBytes1) + _, publicKey2 := btcec.PrivKeyFromBytes(btcec.S256(), privateKeyBytes2) + + p2ms, err := payment.FromPublicKeys([]*btcec.PublicKey{publicKey1, publicKey2}, 1, &network.Regtest) + if err != nil { + t.Error(err) + } + + if hex.EncodeToString(p2ms.Script) != "5121036f5646ed688b9279369da0a4ad78953ae7e6d300436ca8a3264360efe38236e321023c61f59e9a3a3eb01c3ed0cf967ad217153944bcf2498a8fd6e70b27c7ab6ee652ae" { + t.Error("hax value of p2ms script not as expected") + } + +} From 056037a5a82ca83357f1f1c3f1e9af12a19166a4 Mon Sep 17 00:00:00 2001 From: sekulicd Date: Wed, 26 Oct 2022 17:27:07 +0200 Subject: [PATCH 2/2] blinding bug --- psetv2/blinder.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/psetv2/blinder.go b/psetv2/blinder.go index ecb7fc3..70c65c4 100644 --- a/psetv2/blinder.go +++ b/psetv2/blinder.go @@ -443,7 +443,11 @@ func (b *Blinder) blind( } if !isLastBlinder { - p.Global.Scalars = append(b.Pset.Global.Scalars, outputScalar) + outScalar, err := b.generator.SubtractScalars(outputScalar, inputScalar) + if err != nil { + return err + } + p.Global.Scalars = append(b.Pset.Global.Scalars, outScalar) } else { p.Global.Scalars = nil }