tMerge branch 'SomberNight-virtual_tx_size' - electrum - Electrum Bitcoin wallet
 (HTM) git clone https://git.parazyd.org/electrum
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
       ---
 (DIR) commit ff983687a195f03ae8f444b5af58de39490a9831
 (DIR) parent 7b2ff57d0cafba6afa6f77257176e7c77947cada
 (HTM) Author: ThomasV <thomasv@electrum.org>
       Date:   Fri, 22 Sep 2017 09:49:55 +0200
       
       Merge branch 'SomberNight-virtual_tx_size'
       
       Diffstat:
         M lib/tests/test_transaction.py       |      19 +++++++++++++++++++
         M lib/transaction.py                  |      33 +++++++++++++++++++++++++++++--
       
       2 files changed, 50 insertions(+), 2 deletions(-)
       ---
 (DIR) diff --git a/lib/tests/test_transaction.py b/lib/tests/test_transaction.py
       t@@ -18,6 +18,7 @@ from lib.util import bh2u
        unsigned_blob = '01000000012a5c9a94fcde98f5581cd00162c60a13936ceb75389ea65bf38633b424eb4031000000005701ff4c53ff0488b21e03ef2afea18000000089689bff23e1e7fb2f161daa37270a97a3d8c2e537584b2d304ecb47b86d21fc021b010d3bd425f8cf2e04824bfdf1f1f5ff1d51fadd9a41f9e3fb8dd3403b1bfe00000000ffffffff0140420f00000000001976a914230ac37834073a42146f11ef8414ae929feaafc388ac00000000'
        signed_blob = '01000000012a5c9a94fcde98f5581cd00162c60a13936ceb75389ea65bf38633b424eb4031000000006c493046022100a82bbc57a0136751e5433f41cf000b3f1a99c6744775e76ec764fb78c54ee100022100f9e80b7de89de861dc6fb0c1429d5da72c2b6b2ee2406bc9bfb1beedd729d985012102e61d176da16edd1d258a200ad9759ef63adf8e14cd97f53227bae35cdb84d2f6ffffffff0140420f00000000001976a914230ac37834073a42146f11ef8414ae929feaafc388ac00000000'
        v2_blob = "0200000001191601a44a81e061502b7bfbc6eaa1cef6d1e6af5308ef96c9342f71dbf4b9b5000000006b483045022100a6d44d0a651790a477e75334adfb8aae94d6612d01187b2c02526e340a7fd6c8022028bdf7a64a54906b13b145cd5dab21a26bd4b85d6044e9b97bceab5be44c2a9201210253e8e0254b0c95776786e40984c1aa32a7d03efa6bdacdea5f421b774917d346feffffff026b20fa04000000001976a914024db2e87dd7cfd0e5f266c5f212e21a31d805a588aca0860100000000001976a91421919b94ae5cefcdf0271191459157cdb41c4cbf88aca6240700"
       +signed_segwit_blob = "01000000000101b66d722484f2db63e827ebf41d02684fed0c6550e85015a6c9d41ef216a8a6f00000000000fdffffff0280c3c90100000000160014b65ce60857f7e7892b983851c2a8e3526d09e4ab64bac30400000000160014c478ebbc0ab2097706a98e10db7cf101839931c4024730440220789c7d47f876638c58d98733c30ae9821c8fa82b470285dcdf6db5994210bf9f02204163418bbc44af701212ad42d884cc613f3d3d831d2d0cc886f767cca6e0235e012103083a6dc250816d771faa60737bfe78b23ad619f6b458e0a1f1688e3a0605e79c00000000"
        
        class TestBCDataStream(unittest.TestCase):
        
       t@@ -137,6 +138,24 @@ class TestTransaction(unittest.TestCase):
        
                tx.update_signatures(signed_blob)
        
       +        self.assertEqual(tx.estimated_total_size(), 193)
       +        self.assertEqual(tx.estimated_base_size(), 193)
       +        self.assertEqual(tx.estimated_witness_size(), 0)
       +        self.assertEqual(tx.estimated_weight(), 772)
       +        self.assertEqual(tx.estimated_virtual_size(), 193)
       +        self.assertEqual(tx.estimated_size(), 193)
       +
       +    # TODO other tests for segwit tx
       +    def test_tx_signed_segwit(self):
       +        tx = transaction.Transaction(signed_segwit_blob)
       +
       +        self.assertEqual(tx.estimated_total_size(), 222)
       +        self.assertEqual(tx.estimated_base_size(), 113)
       +        self.assertEqual(tx.estimated_witness_size(), 109)
       +        self.assertEqual(tx.estimated_weight(), 561)
       +        self.assertEqual(tx.estimated_virtual_size(), 141)
       +        self.assertEqual(tx.estimated_size(), 141)
       +
            def test_errors(self):
                with self.assertRaises(TypeError):
                    transaction.Transaction.pay_script(output_type=None, addr='')
 (DIR) diff --git a/lib/transaction.py b/lib/transaction.py
       t@@ -825,8 +825,14 @@ class Transaction:
        
            @profiler
            def estimated_size(self):
       -        '''Return an estimated tx size in bytes.'''
       -        return len(self.serialize(True)) // 2 if not self.is_complete() or self.raw is None else len(self.raw) / 2 # ASCII hex string
       +        """Return an estimated virtual tx size in vbytes.
       +        BIP-0141 defines 'Virtual transaction size' to be weight/4 rounded up.
       +        This definition is only for humans, and has little meaning otherwise.
       +        If we wanted sub-byte precision, fee calculation should use transaction
       +        weights, but for simplicity we approximate that with (virtual_size)x4
       +        """
       +        weight = self.estimated_weight()
       +        return weight // 4 + (weight % 4 > 0)
        
            @classmethod
            def estimated_input_size(self, txin):
       t@@ -834,6 +840,29 @@ class Transaction:
                script = self.input_script(txin, True)
                return len(self.serialize_input(txin, script)) // 2
        
       +    def estimated_total_size(self):
       +        """Return an estimated total transaction size in bytes."""
       +        return len(self.serialize(True)) // 2 if not self.is_complete() or self.raw is None else len(self.raw) // 2  # ASCII hex string
       +
       +    def estimated_witness_size(self):
       +        """Return an estimate of witness size in bytes."""
       +        if not self.is_segwit():
       +            return 0
       +        inputs = self.inputs()
       +        witness = ''.join(self.serialize_witness(x) for x in inputs)
       +        witness_size = len(witness) // 2 + 2  # include marker and flag
       +        return witness_size
       +
       +    def estimated_base_size(self):
       +        """Return an estimated base transaction size in bytes."""
       +        return self.estimated_total_size() - self.estimated_witness_size()
       +
       +    def estimated_weight(self):
       +        """Return an estimate of transaction weight."""
       +        total_tx_size = self.estimated_total_size()
       +        base_tx_size = self.estimated_base_size()
       +        return 3 * base_tx_size + total_tx_size
       +
            def signature_count(self):
                r = 0
                s = 0