Repository: bitcoinjs/bitcoinjs-lib
Pull request #811 (2017-06-20 11:49:12)

Add weight / vsize
I will add some simple tests if this concept is OK with you

runn1ng: Hm, `vsize` name is from bitcoin, but it clashes with the naming conventions in the library. `virtualSize` might be better
dcousens: `virtualSize` :+1: 

LGTM
Tests!
runn1ng: Done, the tests seem to be going well on Travis.

The fixtures have vsize that I took by decoding from bitcoind, I took weight as vsize*4 and fiddled with it until it passed (since bitcoind doesn't give me weight).
dcousens: Merge after nit

Patch:
diff --git a/src/transaction.js b/src/transaction.js
index 41e00d90..86ccceab 100644
--- a/src/transaction.js
+++ b/src/transaction.js
@@ -191,6 +191,16 @@ Transaction.prototype.hasWitnesses = function () {
   })
 }
 
+Transaction.prototype.weight = function () {
+  var base = this.__byteLength(false)
+  var total = this.__byteLength(true)
+  return base * 3 + total
+}
+
+Transaction.prototype.virtualSize = function () {
+  return Math.ceil(this.weight() / 4)
+}
+
 Transaction.prototype.byteLength = function () {
   return this.__byteLength(true)
 }


Test patch:
diff --git a/test/fixtures/transaction.json b/test/fixtures/transaction.json
index 7fb51359..6bf60906 100644
--- a/test/fixtures/transaction.json
+++ b/test/fixtures/transaction.json
@@ -22,7 +22,9 @@
         ],
         "locktime": 0
       },
-      "coinbase": false
+      "coinbase": false,
+      "virtualSize": 192,
+      "weight": 768
     },
     {
       "description": "Standard transaction (2:2)",
@@ -57,7 +59,9 @@
         ],
         "locktime": 0
       },
-      "coinbase": false
+      "coinbase": false,
+      "virtualSize": 396,
+      "weight": 1584
     },
     {
       "description": "Standard transaction (14:2)",
@@ -151,7 +155,9 @@
           }
         ]
       },
-      "coinbase": false
+      "coinbase": false,
+      "virtualSize": 2596,
+      "weight": 10384
     },
     {
       "description": "Coinbase transaction",
@@ -175,7 +181,9 @@
         ],
         "locktime": 0
       },
-      "coinbase": true
+      "coinbase": true,
+      "virtualSize": 126,
+      "weight": 504
     },
     {
       "description": "Transaction that ignores script chunking rules - Bug #367",
@@ -227,7 +235,9 @@
           }
         ]
       },
-      "coinbase": false
+      "coinbase": false,
+      "virtualSize": 249,
+      "weight": 996
     },
     {
       "description": "P2PK",
@@ -253,7 +263,9 @@
         ],
         "locktime": 0
       },
-      "coinbase": false
+      "coinbase": false,
+      "virtualSize": 158,
+      "weight": 632
     },
     {
       "description": "P2SH P2PK",
@@ -280,7 +292,9 @@
         ],
         "locktime": 0
       },
-      "coinbase": false
+      "coinbase": false,
+      "virtualSize": 193,
+      "weight": 772
     },
     {
       "description": "P2WSH P2PK",
@@ -309,7 +323,9 @@
         ],
         "locktime": 0
       },
-      "coinbase": false
+      "coinbase": false,
+      "virtualSize": 113,
+      "weight": 451
     },
     {
       "description": "P2SH P2WSH P2PK",
@@ -338,7 +354,9 @@
         ],
         "locktime": 0
       },
-      "coinbase": false
+      "coinbase": false,
+      "virtualSize": 148,
+      "weight": 591
     },
     {
       "description": "P2PKH",
@@ -363,7 +381,9 @@
         ],
         "locktime": 0
       },
-      "coinbase": false
+      "coinbase": false,
+      "virtualSize": 192,
+      "weight": 768
     },
     {
       "description": "P2SH P2PKH",
@@ -388,7 +408,9 @@
         ],
         "locktime": 0
       },
-      "coinbase": false
+      "coinbase": false,
+      "virtualSize": 217,
+      "weight": 868
     },
     {
       "description": "P2WSH P2PKH",
@@ -419,7 +441,9 @@
         ],
         "locktime": 0
       },
-      "coinbase": false
+      "coinbase": false,
+      "virtualSize": 119,
+      "weight": 476
     },
     {
       "description": "P2SH P2WSH P2PKH",
@@ -449,7 +473,9 @@
         ],
         "locktime": 0
       },
-      "coinbase": false
+      "coinbase": false,
+      "virtualSize": 154,
+      "weight": 616
     },
     {
       "description": "Multisig",
@@ -474,7 +500,9 @@
         ],
         "locktime": 0
       },
-      "coinbase": false
+      "coinbase": false,
+      "virtualSize": 159,
+      "weight": 636
     },
     {
       "description": "P2SH Multisig",
@@ -500,7 +528,9 @@
         ],
         "locktime": 0
       },
-      "coinbase": false
+      "coinbase": false,
+      "virtualSize": 196,
+      "weight": 784
     },
     {
       "description": "P2WSH Multisig",
@@ -530,7 +560,9 @@
         ],
         "locktime": 0
       },
-      "coinbase": false
+      "coinbase": false,
+      "virtualSize": 114,
+      "weight": 455
     },
     {
       "description": "P2SH P2WSH Multisig",
@@ -561,7 +593,9 @@
         ],
         "locktime": 0
       },
-      "coinbase": false
+      "coinbase": false,
+      "virtualSize": 149,
+      "weight": 595
     },
     {
       "description": "P2WKH",
@@ -590,7 +624,9 @@
         ],
         "locktime": 0
       },
-      "coinbase": false
+      "coinbase": false,
+      "virtualSize": 113,
+      "weight": 450
     },
     {
       "description": "P2SH P2WKH",
@@ -619,7 +655,9 @@
         ],
         "locktime": 0
       },
-      "coinbase": false
+      "coinbase": false,
+      "virtualSize": 136,
+      "weight": 542
     },
     {
       "description": "Coinbase transaction w/ witness",
@@ -652,7 +690,9 @@
         ],
         "locktime": 0
       },
-      "coinbase": true
+      "coinbase": true,
+      "virtualSize": 156,
+      "weight": 624
     }
   ],
   "hashForSignature": [
diff --git a/test/transaction.js b/test/transaction.js
index 35beb81a..62c24d01 100644
--- a/test/transaction.js
+++ b/test/transaction.js
@@ -129,6 +129,24 @@ describe('Transaction', function () {
     })
   })
 
+  describe('weight/virtualSize', function () {
+    it('computes virtual size', function () {
+      fixtures.valid.forEach(function (f) {
+        var transaction = Transaction.fromHex(f.whex ? f.whex : f.hex)
+
+        assert.strictEqual(transaction.virtualSize(), f.virtualSize)
+      })
+    })
+
+    it('computes weight', function () {
+      fixtures.valid.forEach(function (f) {
+        var transaction = Transaction.fromHex(f.whex ? f.whex : f.hex)
+
+        assert.strictEqual(transaction.weight(), f.weight)
+      })
+    })
+  })
+
   describe('addInput', function () {
     var prevTxHash
     beforeEach(function () {