From 8a5104c33366da88d56b1102be261fe81a9e35d9 Mon Sep 17 00:00:00 2001
From: junderw <junderwood@bitcoinbank.co.jp>
Date: Thu, 11 Jul 2019 11:09:05 +0900
Subject: [PATCH] Add tests

---
 test/fixtures/psbt.json | 18 ++++++++---
 test/psbt.js            | 68 ++++++++++++++++++++++++++++++++---------
 2 files changed, 67 insertions(+), 19 deletions(-)

diff --git a/test/fixtures/psbt.json b/test/fixtures/psbt.json
index aeed39d..61ab114 100644
--- a/test/fixtures/psbt.json
+++ b/test/fixtures/psbt.json
@@ -314,7 +314,7 @@
         "exception": "Error adding input."
       },
       {
-        "description": "checks for hash and index",
+        "description": "should be equal",
         "inputData": {
           "hash": "Buffer.from('000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f', 'hex')",
           "index": 2
@@ -326,12 +326,19 @@
   "addOutput": {
     "checks": [
       {
-        "description": "checks for hash and index",
+        "description": "Checks value is number",
         "outputData": {
           "address": "1P2NFEBp32V2arRwZNww6tgXEV58FG94mr",
           "value": "xyz"
         },
         "exception": "Error adding output."
+      },
+      {
+        "description": "Adds output normally",
+        "outputData": {
+          "address": "1P2NFEBp32V2arRwZNww6tgXEV58FG94mr",
+          "value": 42
+        }
       }
     ]
   },
@@ -446,8 +453,8 @@
     },
     {
       "type": "P2WPKH",
-      "psbt": "cHNidP8BAFUCAAAAAQgW434j2ReNazU0B0+Wa45cPWyUkrl6beWc1ZA6s7qYAAAAAAD/////AYA4AQAAAAAAGXapFC6fT3nay4TXcKcXnM8ZZ89Pmi8xiKwAAAAAAAEAvAIAAAABX6KFQJqSuzjln4vq33jes8S/HAJw/W8fB2hmYJvF95AAAAAAakcwRAIgBfylcQEFaoyuzZcVT1AG3nU3FxDE2ZRNSQbH0Pb38pkCIBh+SztZRlITl/WbdA/Z7SVsVqApPeT1HmzpiLcunN4yASECHwUJGd/AygUjfs6zraDrLcjE5arbSBzHCVX/DQD3tuf/////AZBfAQAAAAAAFgAU2gkxRpZzSTR+etKYJ+B243D+sbYAAAAAIgIDV7l7X08dWtzMR2saPXJo782Tot5+PQBMZZOm3GGTUHpIMEUCIQDxPCn2fwfxoYgGVyi5++mXNAmCX2wWRS7LuJB2qQkMVQIgHsxylMEWd7ladApdSpnEtSwWb4/QJGOnsDGZCPxvfucBAAA=",
-      "result": "cHNidP8BAFUCAAAAAQgW434j2ReNazU0B0+Wa45cPWyUkrl6beWc1ZA6s7qYAAAAAAD/////AYA4AQAAAAAAGXapFC6fT3nay4TXcKcXnM8ZZ89Pmi8xiKwAAAAAAAEAvAIAAAABX6KFQJqSuzjln4vq33jes8S/HAJw/W8fB2hmYJvF95AAAAAAakcwRAIgBfylcQEFaoyuzZcVT1AG3nU3FxDE2ZRNSQbH0Pb38pkCIBh+SztZRlITl/WbdA/Z7SVsVqApPeT1HmzpiLcunN4yASECHwUJGd/AygUjfs6zraDrLcjE5arbSBzHCVX/DQD3tuf/////AZBfAQAAAAAAFgAU2gkxRpZzSTR+etKYJ+B243D+sbYAAAAAAQcAAAA="
+      "psbt": "cHNidP8BAFICAAAAAb5UIQFSoXPjqxSmuiSZkM5PjaycnrXQ6VB+u2+MzbSGAAAAAAD/////ASBOAAAAAAAAFgAUXsVBEaHSlhycDORbHHtBKwDo4zIAAAAAAAEBHzB1AAAAAAAAFgAUvIgag7HZu7Rjd/ugmJC/MHlZmAYiAgLN1zezMD4c4uegTbgfJ1GCtN5/hlJYaJt7e8mt1BVzIEcwRAIgXhgL5G81tXP7MAaKJtA0QaFu17bLocOGqxXmDoIfYUACIAOIynpoPS/dTz9Omg2h7v5kiql7ab0SPzWDdxpvpsUcAQAA",
+      "result": "cHNidP8BAFICAAAAAb5UIQFSoXPjqxSmuiSZkM5PjaycnrXQ6VB+u2+MzbSGAAAAAAD/////ASBOAAAAAAAAFgAUXsVBEaHSlhycDORbHHtBKwDo4zIAAAAAAAEBHzB1AAAAAAAAFgAUvIgag7HZu7Rjd/ugmJC/MHlZmAYBCGsCRzBEAiBeGAvkbzW1c/swBoom0DRBoW7Xtsuhw4arFeYOgh9hQAIgA4jKemg9L91PP06aDaHu/mSKqXtpvRI/NYN3Gm+mxRwBIQLN1zezMD4c4uegTbgfJ1GCtN5/hlJYaJt7e8mt1BVzIAAA"
     },
     {
       "type": "P2WSH-P2PK",
@@ -478,5 +485,8 @@
       "nonWitnessUtxo": "Buffer.from('0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f618765000000', 'hex')",
       "inputIndex": 0
     }
+  },
+  "clone": {
+    "psbt": "cHNidP8BAKYCAAAAAlwKQ3suPWwEJ/zQ9sZsIioOcHKU1KoLMxlMNSXVIkEWAAAAAAD/////YYDJMap+mYgbTrCNAdpWHN+EkKvl+XYao/6co/EQfwMAAAAAAP////8CkF8BAAAAAAAWABRnPBAmVHz2HL+8/1U+QG5L2thjmjhKAAAAAAAAIgAg700yfFRyhWzQnPHIUb/XQqsjlpf4A0uw682pCVWuQ8IAAAAAAAEBKzB1AAAAAAAAIgAgth9oE4cDfC5aV58VgkW5CptHsIxppYzJV8C5kT6aTo8iAgNfNgnFnEPS9s4PY/I5bezpWiAEzQ4DRTASgdSdeMM06UgwRQIhALO0xRpuqP3aVkm+DPykrtqe6fPNSgNblp9K9MAwmtHJAiAHV5ZvZN8Vi49n/o9ISFyvtHsPXXPKqBxC9m2m2HlpYgEBBSMhA182CcWcQ9L2zg9j8jlt7OlaIATNDgNFMBKB1J14wzTprAABASuAOAEAAAAAACIAILYfaBOHA3wuWlefFYJFuQqbR7CMaaWMyVfAuZE+mk6PIgIDXzYJxZxD0vbOD2PyOW3s6VogBM0OA0UwEoHUnXjDNOlIMEUCIQC6XN6tpo9mYlZej4BXSSh5D1K6aILBfQ4WBWXUrISx6wIgVaxFUsz8y59xJ1V4sZ1qarHX9pZ+MJmLKbl2ZSadisoBAQUjIQNfNgnFnEPS9s4PY/I5bezpWiAEzQ4DRTASgdSdeMM06awAAAA="
   }
 }
diff --git a/test/psbt.js b/test/psbt.js
index 0ccd8ef..99bd9c1 100644
--- a/test/psbt.js
+++ b/test/psbt.js
@@ -28,7 +28,7 @@ describe(`Psbt`, () => {
       it(`Invalid: ${f.description}`, () => {
         assert.throws(() => {
           Psbt.fromBase64(f.psbt)
-        }, {message: f.errorMessage})
+        }, new RegExp(f.errorMessage))
       })
     })
 
@@ -46,7 +46,7 @@ describe(`Psbt`, () => {
         const psbt =  Psbt.fromBase64(f.psbt)
         assert.throws(() => {
           psbt.signInput(f.inputToCheck, keyPair)
-        }, {message: f.errorMessage})
+        }, new RegExp(f.errorMessage))
       })
     })
 
@@ -181,7 +181,7 @@ describe(`Psbt`, () => {
             f.shouldThrow.inputToCheck,
             ECPair.fromWIF(f.shouldThrow.WIF),
           )
-        }, {message: f.shouldThrow.errorMessage})
+        }, new RegExp(f.shouldThrow.errorMessage))
         assert.rejects(async () => {
           await psbtThatShouldThrow.signInputAsync(
             f.shouldThrow.inputToCheck,
@@ -208,7 +208,7 @@ describe(`Psbt`, () => {
             f.shouldThrow.inputToCheck,
             ECPair.fromWIF(f.shouldThrow.WIF),
           )
-        }, {message: f.shouldThrow.errorMessage})
+        }, new RegExp(f.shouldThrow.errorMessage))
         assert.throws(() => {
           psbtThatShouldThrow.signInput(
             f.shouldThrow.inputToCheck,
@@ -276,6 +276,23 @@ describe(`Psbt`, () => {
         assert.strictEqual(psbt.toBase64(), f.result)
       })
     })
+    it('fails if no script found', () => {
+      const psbt = new Psbt()
+      psbt.addInput({
+        hash: '0000000000000000000000000000000000000000000000000000000000000000',
+        index: 0
+      })
+      assert.throws(() => {
+        psbt.finalizeAllInputs()
+      }, new RegExp('No script found for input #0'))
+      psbt.addWitnessUtxoToInput(0, {
+        script: Buffer.from('0014d85c2b71d0060b09c9886aeb815e50991dda124d', 'hex'),
+        value: 2e5
+      })
+      assert.throws(() => {
+        psbt.finalizeAllInputs()
+      }, new RegExp('Can not finalize input #0'))
+    })
   })
 
   describe('fromTransaction', () => {
@@ -289,9 +306,6 @@ describe(`Psbt`, () => {
 
   describe('addInput', () => {
     fixtures.addInput.checks.forEach(f => {
-      for (const attr of Object.keys(f.inputData)) {
-        f.inputData[attr] = f.inputData[attr]
-      }
       it(f.description, () => {
         const psbt = new Psbt()
 
@@ -299,13 +313,14 @@ describe(`Psbt`, () => {
           assert.throws(() => {
             psbt.addInput(f.inputData)
           }, new RegExp(f.exception))
+          assert.throws(() => {
+            psbt.addInputs([f.inputData])
+          }, new RegExp(f.exception))
         } else {
           assert.doesNotThrow(() => {
-            psbt.addInput(f.inputData)
+            psbt.addInputs([f.inputData])
             if (f.equals) {
               assert.strictEqual(psbt.toBase64(), f.equals)
-            } else {
-              console.log(psbt.toBase64())
             }
           })
           assert.throws(() => {
@@ -318,9 +333,6 @@ describe(`Psbt`, () => {
 
   describe('addOutput', () => {
     fixtures.addOutput.checks.forEach(f => {
-      for (const attr of Object.keys(f.outputData)) {
-        f.outputData[attr] = f.outputData[attr]
-      }
       it(f.description, () => {
         const psbt = new Psbt()
 
@@ -328,10 +340,15 @@ describe(`Psbt`, () => {
           assert.throws(() => {
             psbt.addOutput(f.outputData)
           }, new RegExp(f.exception))
+          assert.throws(() => {
+            psbt.addOutputs([f.outputData])
+          }, new RegExp(f.exception))
         } else {
           assert.doesNotThrow(() => {
             psbt.addOutput(f.outputData)
-            console.log(psbt.toBase64())
+          })
+          assert.doesNotThrow(() => {
+            psbt.addOutputs([f.outputData])
           })
         }
       })
@@ -381,7 +398,26 @@ describe(`Psbt`, () => {
 
       assert.throws(() => {
         psbt.setSequence(1, 0)
-      }, {message: 'Input index too high'})
+      }, new RegExp('Input index too high'))
+    })
+  })
+
+  describe('clone', () => {
+    it('Should clone a psbt exactly with no reference', () => {
+      const f = fixtures.clone
+      const psbt = Psbt.fromBase64(f.psbt)
+      const notAClone = Object.assign(new Psbt(), psbt) // references still active
+      const clone = psbt.clone()
+
+      assert.strictEqual(psbt.validateAllSignatures(), true)
+
+      assert.strictEqual(clone.toBase64(), psbt.toBase64())
+      assert.strictEqual(clone.toBase64(), notAClone.toBase64())
+      assert.strictEqual(psbt.toBase64(), notAClone.toBase64())
+      psbt.globalMap.unsignedTx[3] = 0xff
+      assert.notStrictEqual(clone.toBase64(), psbt.toBase64())
+      assert.notStrictEqual(clone.toBase64(), notAClone.toBase64())
+      assert.strictEqual(psbt.toBase64(), notAClone.toBase64())
     })
   })
 
@@ -427,6 +463,8 @@ describe(`Psbt`, () => {
       psbt.finalizeAllInputs()
 
       assert.strictEqual(psbt.getFeeRate(), f.fee)
+      psbt.__CACHE.__FEE_RATE = undefined
+      assert.strictEqual(psbt.getFeeRate(), f.fee)
     })
   })