From 28d4542a0ac77a30a242d0568e580a5b437f53fa Mon Sep 17 00:00:00 2001
From: Matt Corallo <git@bluematt.me>
Date: Wed, 20 Sep 2017 20:19:14 -0400
Subject: [PATCH] Disallow uncompressed pubkeys in bitcoin-tx [multisig] output
 adds

---
 Makefile.am                           |  1 +
 src/bitcoin-tx.cpp                    |  8 ++++++++
 test/util/data/bitcoin-util-test.json | 18 ++++++++++++++++++
 test/util/data/txcreatemultisig5.json | 26 ++++++++++++++++++++++++++
 4 files changed, 53 insertions(+)
 create mode 100644 test/util/data/txcreatemultisig5.json

diff --git a/Makefile.am b/Makefile.am
index 8216b7d60..3b62a1060 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -249,6 +249,7 @@ EXTRA_DIST += \
     test/util/data/txcreatemultisig3.json \
     test/util/data/txcreatemultisig4.hex \
     test/util/data/txcreatemultisig4.json \
+    test/util/data/txcreatemultisig5.json \
     test/util/data/txcreateoutpubkey1.hex \
     test/util/data/txcreateoutpubkey1.json \
     test/util/data/txcreateoutpubkey2.hex \
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index d8d7934bf..e4f44435b 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -310,6 +310,9 @@ static void MutateTxAddOutPubKey(CMutableTransaction& tx, const std::string& str
     }
 
     if (bSegWit) {
+        if (!pubkey.IsCompressed()) {
+            throw std::runtime_error("Uncompressed pubkeys are not useable for SegWit outputs");
+        }
         // Call GetScriptForWitness() to build a P2WSH scriptPubKey
         scriptPubKey = GetScriptForWitness(scriptPubKey);
     }
@@ -375,6 +378,11 @@ static void MutateTxAddOutMultiSig(CMutableTransaction& tx, const std::string& s
     CScript scriptPubKey = GetScriptForMultisig(required, pubkeys);
 
     if (bSegWit) {
+        for (CPubKey& pubkey : pubkeys) {
+            if (!pubkey.IsCompressed()) {
+                throw std::runtime_error("Uncompressed pubkeys are not useable for SegWit outputs");
+            }
+        }
         // Call GetScriptForWitness() to build a P2WSH scriptPubKey
         scriptPubKey = GetScriptForWitness(scriptPubKey);
     }
diff --git a/test/util/data/bitcoin-util-test.json b/test/util/data/bitcoin-util-test.json
index b61a4f7f8..89b28bba6 100644
--- a/test/util/data/bitcoin-util-test.json
+++ b/test/util/data/bitcoin-util-test.json
@@ -261,6 +261,13 @@
     "output_cmp": "txcreateoutpubkey3.json",
     "description": "Creates a new transaction with a single pay-to-pub-key output, wrapped in P2SH (output as json)"
   },
+  { "exec": "./bitcoin-tx",
+    "args":
+    ["-json", "-create", "outpubkey=0:047d1368ba7ae01c94bc32293efd70bd7e3be7aa7912d07d0b1c659c1008d179b8642f5fb90f47580feb29f045e216ff5a4716d3a0fed36da414d332046303c44a:WS", "nversion=1"],
+    "return_code": 1,
+    "error_txt": "error: Uncompressed pubkeys are not useable for SegWit outputs",
+    "description": "Creates a new transaction with a single pay-to-pub-key output, wrapped in P2SH (output as json)"
+  },
   { "exec": "./bitcoin-tx",
     "args":
     ["-create",
@@ -388,5 +395,16 @@
     "args": ["-json", "-create", "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485:WS", "nversion=1"],
     "output_cmp": "txcreatemultisig4.json",
     "description": "Creates a new transaction with a single 2-of-3 multisig in a P2WSH output, wrapped in P2SH (output in json)"
+  },
+  { "exec": "./bitcoin-tx",
+    "args": ["-json", "-create", "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:047d1368ba7ae01c94bc32293efd70bd7e3be7aa7912d07d0b1c659c1008d179b8642f5fb90f47580feb29f045e216ff5a4716d3a0fed36da414d332046303c44a:S"],
+    "output_cmp": "txcreatemultisig5.json",
+    "description": "Uncompressed pubkeys should work just fine for non-witness outputs"
+  },
+  { "exec": "./bitcoin-tx",
+    "args": ["-json", "-create", "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:047d1368ba7ae01c94bc32293efd70bd7e3be7aa7912d07d0b1c659c1008d179b8642f5fb90f47580feb29f045e216ff5a4716d3a0fed36da414d332046303c44a:WS"],
+    "return_code": 1,
+    "error_txt": "error: Uncompressed pubkeys are not useable for SegWit outputs",
+    "description": "Ensure adding witness outputs with uncompressed pubkeys fails"
   }
 ]
diff --git a/test/util/data/txcreatemultisig5.json b/test/util/data/txcreatemultisig5.json
new file mode 100644
index 000000000..20e9bb077
--- /dev/null
+++ b/test/util/data/txcreatemultisig5.json
@@ -0,0 +1,26 @@
+{
+    "txid": "813cf75e1f08debd242ef7c8192b7d478fb651355209369499a0de779ba7eb2f",
+    "hash": "813cf75e1f08debd242ef7c8192b7d478fb651355209369499a0de779ba7eb2f",
+    "version": 2,
+    "size": 42,
+    "vsize": 42,
+    "locktime": 0,
+    "vin": [
+    ],
+    "vout": [
+        {
+            "value": 1.00000000,
+            "n": 0,
+            "scriptPubKey": {
+                "asm": "OP_HASH160 a4051c02398868af83f28f083208fae99a769263 OP_EQUAL",
+                "hex": "a914a4051c02398868af83f28f083208fae99a76926387",
+                "reqSigs": 1,
+                "type": "scripthash",
+                "addresses": [
+                    "3GeGs1eHUxPz5YyuFe9WPpXid2UsUb5Jos"
+                ]
+            }
+        }
+    ],
+    "hex": "02000000000100e1f5050000000017a914a4051c02398868af83f28f083208fae99a7692638700000000"
+}