~ubuntu-branches/debian/stretch/electrum/stretch

« back to all changes in this revision

Viewing changes to lib/transaction.py

  • Committer: Package Import Robot
  • Author(s): Tristan Seligmann
  • Date: 2016-04-04 03:02:39 UTC
  • mfrom: (1.1.10)
  • Revision ID: package-import@ubuntu.com-20160404030239-0szgkio8yryjv7c9
Tags: 2.6.3-1
* New upstream release.
  - Drop backported install-wizard-connect.patch.
* Add Suggests: python-zbar and update the installation hint to suggest
  apt-get instead of pip (closes: #819517).
* Bump Standards-Version to 3.9.7 (no changes).
* Update Vcs-* links.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!/usr/bin/env python
2
2
#
3
3
# Electrum - lightweight Bitcoin client
4
 
# Copyright (C) 2011 thomasv@gitorious
5
 
#
6
 
# This program is free software: you can redistribute it and/or modify
7
 
# it under the terms of the GNU General Public License as published by
8
 
# the Free Software Foundation, either version 3 of the License, or
9
 
# (at your option) any later version.
10
 
#
11
 
# This program is distributed in the hope that it will be useful,
12
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
 
# GNU General Public License for more details.
15
 
#
16
 
# You should have received a copy of the GNU General Public License
17
 
# along with this program. If not, see <http://www.gnu.org/licenses/>.
 
4
# Copyright (C) 2011 Thomas Voegtlin
 
5
#
 
6
# Permission is hereby granted, free of charge, to any person
 
7
# obtaining a copy of this software and associated documentation files
 
8
# (the "Software"), to deal in the Software without restriction,
 
9
# including without limitation the rights to use, copy, modify, merge,
 
10
# publish, distribute, sublicense, and/or sell copies of the Software,
 
11
# and to permit persons to whom the Software is furnished to do so,
 
12
# subject to the following conditions:
 
13
#
 
14
# The above copyright notice and this permission notice shall be
 
15
# included in all copies or substantial portions of the Software.
 
16
#
 
17
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
18
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
19
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 
20
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 
21
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 
22
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
23
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 
24
# SOFTWARE.
 
25
 
18
26
 
19
27
 
20
28
# Note: The deserialization code originally comes from ABE.
22
30
 
23
31
import bitcoin
24
32
from bitcoin import *
25
 
from util import print_error
 
33
from util import print_error, profiler
26
34
import time
27
35
import sys
28
36
import struct
36
44
 
37
45
NO_SIGNATURE = 'ff'
38
46
 
 
47
 
39
48
class SerializationError(Exception):
40
49
    """ Thrown when there's a problem deserializing or serializing """
41
50
 
393
402
    # 65 BYTES:... CHECKSIG
394
403
    match = [ opcodes.OP_PUSHDATA4, opcodes.OP_CHECKSIG ]
395
404
    if match_decoded(decoded, match):
396
 
        return 'pubkey', decoded[0][1].encode('hex')
 
405
        return TYPE_PUBKEY, decoded[0][1].encode('hex')
397
406
 
398
407
    # Pay-by-Bitcoin-address TxOuts look like:
399
408
    # DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG
400
409
    match = [ opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG ]
401
410
    if match_decoded(decoded, match):
402
 
        return 'address', hash_160_to_bc_address(decoded[2][1])
 
411
        return TYPE_ADDRESS, hash_160_to_bc_address(decoded[2][1])
403
412
 
404
413
    # p2sh
405
414
    match = [ opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUAL ]
406
415
    if match_decoded(decoded, match):
407
 
        return 'address', hash_160_to_bc_address(decoded[1][1],5)
 
416
        return TYPE_ADDRESS, hash_160_to_bc_address(decoded[1][1],5)
408
417
 
409
 
    return 'script', bytes
 
418
    return TYPE_SCRIPT, bytes
410
419
 
411
420
 
412
421
 
478
487
            self.raw = raw['hex']
479
488
        else:
480
489
            raise BaseException("cannot initialize transaction", raw)
481
 
        self.inputs = None
 
490
        self._inputs = None
 
491
        self._outputs = None
482
492
 
483
493
    def update(self, raw):
484
494
        self.raw = raw
485
 
        self.inputs = None
 
495
        self._inputs = None
486
496
        self.deserialize()
487
497
 
 
498
    def inputs(self):
 
499
        if self._inputs is None:
 
500
            self.deserialize()
 
501
        return self._inputs
 
502
 
 
503
    def outputs(self):
 
504
        if self._outputs is None:
 
505
            self.deserialize()
 
506
        return self._outputs
 
507
 
488
508
    def update_signatures(self, raw):
489
509
        """Add new signatures to a transaction"""
490
510
        d = deserialize(raw)
491
 
        for i, txin in enumerate(self.inputs):
 
511
        for i, txin in enumerate(self.inputs()):
492
512
            sigs1 = txin.get('signatures')
493
513
            sigs2 = d['inputs'][i].get('signatures')
494
514
            for sig in sigs2:
508
528
                        public_key.verify_digest(sig_string, for_sig, sigdecode = ecdsa.util.sigdecode_string)
509
529
                        j = pubkeys.index(pubkey)
510
530
                        print_error("adding sig", i, j, pubkey, sig)
511
 
                        self.inputs[i]['signatures'][j] = sig
512
 
                        self.inputs[i]['x_pubkeys'][j] = pubkey
 
531
                        self._inputs[i]['signatures'][j] = sig
 
532
                        self._inputs[i]['x_pubkeys'][j] = pubkey
513
533
                        break
514
534
        # redo raw
515
535
        self.raw = self.serialize()
518
538
    def deserialize(self):
519
539
        if self.raw is None:
520
540
            self.raw = self.serialize()
521
 
        if self.inputs is not None:
 
541
        if self._inputs is not None:
522
542
            return
523
543
        d = deserialize(self.raw)
524
 
        self.inputs = d['inputs']
525
 
        self.outputs = [(x['type'], x['address'], x['value']) for x in d['outputs']]
 
544
        self._inputs = d['inputs']
 
545
        self._outputs = [(x['type'], x['address'], x['value']) for x in d['outputs']]
526
546
        self.locktime = d['lockTime']
527
547
        return d
528
548
 
529
549
    @classmethod
530
550
    def from_io(klass, inputs, outputs, locktime=0):
531
551
        self = klass(None)
532
 
        self.inputs = inputs
533
 
        self.outputs = outputs
 
552
        self._inputs = inputs
 
553
        self._outputs = outputs
534
554
        self.locktime = locktime
535
555
        return self
536
556
 
542
562
            pubkey = public_key_from_private_key(privkey)
543
563
            address = address_from_private_key(privkey)
544
564
            u = network.synchronous_get(('blockchain.address.listunspent',[address]))
545
 
            pay_script = klass.pay_script('address', address)
 
565
            pay_script = klass.pay_script(TYPE_ADDRESS, address)
546
566
            for item in u:
547
567
                item['scriptPubKey'] = pay_script
548
568
                item['redeemPubkey'] = pubkey
560
580
            return
561
581
 
562
582
        total = sum(i.get('value') for i in inputs) - fee
563
 
        outputs = [('address', to_address, total)]
 
583
        outputs = [(TYPE_ADDRESS, to_address, total)]
564
584
        self = klass.from_io(inputs, outputs)
565
585
        self.sign(keypairs)
566
586
        return self
577
597
 
578
598
    @classmethod
579
599
    def pay_script(self, output_type, addr):
580
 
        if output_type == 'script':
 
600
        if output_type == TYPE_SCRIPT:
581
601
            return addr.encode('hex')
582
 
        elif output_type == 'address':
 
602
        elif output_type == TYPE_ADDRESS:
583
603
            addrtype, hash_160 = bc_address_to_hash_160(addr)
584
604
            if addrtype == 0:
585
605
                script = '76a9'                                      # op_dup, op_hash_160
595
615
            raise
596
616
        return script
597
617
 
 
618
    @classmethod
598
619
    def input_script(self, txin, i, for_sig):
599
620
        # for_sig:
600
621
        #   -1   : do not sign, estimate length
635
656
                script += push_script(redeem_script)
636
657
 
637
658
        elif for_sig==i:
638
 
            script = txin['redeemScript'] if p2sh else self.pay_script('address', address)
 
659
            script = txin['redeemScript'] if p2sh else self.pay_script(TYPE_ADDRESS, address)
639
660
        else:
640
661
            script = ''
641
662
 
642
663
        return script
643
664
 
 
665
    @classmethod
 
666
    def serialize_input(self, txin, i, for_sig):
 
667
        # Prev hash and index
 
668
        s = txin['prevout_hash'].decode('hex')[::-1].encode('hex')
 
669
        s += int_to_hex(txin['prevout_n'], 4)
 
670
        # Script length, script, sequence
 
671
        script = self.input_script(txin, i, for_sig)
 
672
        s += var_int(len(script) / 2)
 
673
        s += script
 
674
        s += "ffffffff"
 
675
        return s
 
676
 
644
677
    def BIP_LI01_sort(self):
645
678
        # See https://github.com/kristovatlas/rfc/blob/master/bips/bip-li01.mediawiki
646
 
        self.inputs.sort(key = lambda i: (i['prevout_hash'], i['prevout_n']))
647
 
        self.outputs.sort(key = lambda o: (o[2], self.pay_script(o[0], o[1])))
 
679
        self._inputs.sort(key = lambda i: (i['prevout_hash'], i['prevout_n']))
 
680
        self._outputs.sort(key = lambda o: (o[2], self.pay_script(o[0], o[1])))
648
681
 
649
682
    def serialize(self, for_sig=None):
650
 
        inputs = self.inputs
651
 
        outputs = self.outputs
 
683
        inputs = self.inputs()
 
684
        outputs = self.outputs()
652
685
        s  = int_to_hex(1,4)                                         # version
653
686
        s += var_int( len(inputs) )                                  # number of inputs
654
687
        for i, txin in enumerate(inputs):
655
 
            s += txin['prevout_hash'].decode('hex')[::-1].encode('hex')   # prev hash
656
 
            s += int_to_hex(txin['prevout_n'], 4)                         # prev index
657
 
            script = self.input_script(txin, i, for_sig)
658
 
            s += var_int( len(script)/2 )                            # script length
659
 
            s += script
660
 
            s += "ffffffff"                                          # sequence
 
688
            s += self.serialize_input(txin, i, for_sig)
661
689
        s += var_int( len(outputs) )                                 # number of outputs
662
690
        for output in outputs:
663
691
            output_type, addr, amount = output
676
704
    def hash(self):
677
705
        return Hash(self.raw.decode('hex') )[::-1].encode('hex')
678
706
 
679
 
    def add_input(self, input):
680
 
        self.inputs.append(input)
 
707
    def add_inputs(self, inputs):
 
708
        self._inputs.extend(inputs)
 
709
        self.raw = None
 
710
 
 
711
    def add_outputs(self, outputs):
 
712
        self._outputs.extend(outputs)
681
713
        self.raw = None
682
714
 
683
715
    def input_value(self):
684
 
        return sum(x['value'] for x in self.inputs)
 
716
        return sum(x['value'] for x in self.inputs())
685
717
 
686
718
    def output_value(self):
687
 
        return sum( val for tp,addr,val in self.outputs)
 
719
        return sum( val for tp,addr,val in self.outputs())
688
720
 
689
721
    def get_fee(self):
690
722
        return self.input_value() - self.output_value()
691
723
 
 
724
    def is_final(self):
 
725
        return not any([x.get('sequence') < 0xffffffff - 1 for x in self.inputs()])
 
726
 
 
727
    @profiler
 
728
    def estimated_size(self):
 
729
        '''Return an estimated tx size in bytes.'''
 
730
        return len(self.serialize(-1)) / 2  # ASCII hex string
 
731
 
 
732
    @classmethod
 
733
    def estimated_input_size(self, txin):
 
734
        '''Return an estimated of serialized input size in bytes.'''
 
735
        return len(self.serialize_input(txin, -1, -1)) / 2
 
736
 
692
737
    def signature_count(self):
693
738
        r = 0
694
739
        s = 0
695
 
        for txin in self.inputs:
 
740
        for txin in self.inputs():
696
741
            if txin.get('is_coinbase'):
697
742
                continue
698
743
            signatures = filter(None, txin.get('signatures',[]))
706
751
 
707
752
    def inputs_without_script(self):
708
753
        out = set()
709
 
        for i, txin in enumerate(self.inputs):
 
754
        for i, txin in enumerate(self.inputs()):
710
755
            if txin.get('scriptSig') == '':
711
756
                out.add(i)
712
757
        return out
713
758
 
714
759
    def inputs_to_sign(self):
715
760
        out = set()
716
 
        for txin in self.inputs:
 
761
        for txin in self.inputs():
717
762
            num_sig = txin.get('num_sig')
718
763
            if num_sig is None:
719
764
                continue
730
775
        return out
731
776
 
732
777
    def sign(self, keypairs):
733
 
        for i, txin in enumerate(self.inputs):
 
778
        for i, txin in enumerate(self.inputs()):
734
779
            num = txin['num_sig']
735
780
            for x_pubkey in txin['x_pubkeys']:
736
781
                signatures = filter(None, txin['signatures'])
740
785
                if x_pubkey in keypairs.keys():
741
786
                    print_error("adding signature for", x_pubkey)
742
787
                    # add pubkey to txin
743
 
                    txin = self.inputs[i]
 
788
                    txin = self._inputs[i]
744
789
                    x_pubkeys = txin['x_pubkeys']
745
790
                    ii = x_pubkeys.index(x_pubkey)
746
791
                    sec = keypairs[x_pubkey]
747
792
                    pubkey = public_key_from_private_key(sec)
748
793
                    txin['x_pubkeys'][ii] = pubkey
749
794
                    txin['pubkeys'][ii] = pubkey
750
 
                    self.inputs[i] = txin
 
795
                    self._inputs[i] = txin
751
796
                    # add signature
752
797
                    for_sig = Hash(self.tx_for_sig(i).decode('hex'))
753
798
                    pkey = regenerate_key(sec)
757
802
                    sig = private_key.sign_digest_deterministic( for_sig, hashfunc=hashlib.sha256, sigencode = ecdsa.util.sigencode_der )
758
803
                    assert public_key.verify_digest( sig, for_sig, sigdecode = ecdsa.util.sigdecode_der)
759
804
                    txin['signatures'][ii] = sig.encode('hex')
760
 
                    self.inputs[i] = txin
 
805
                    self._inputs[i] = txin
761
806
        print_error("is_complete", self.is_complete())
762
807
        self.raw = self.serialize()
763
808
 
765
810
    def get_outputs(self):
766
811
        """convert pubkeys to addresses"""
767
812
        o = []
768
 
        for type, x, v in self.outputs:
769
 
            if type == 'address':
 
813
        for type, x, v in self.outputs():
 
814
            if type == TYPE_ADDRESS:
770
815
                addr = x
771
 
            elif type == 'pubkey':
 
816
            elif type == TYPE_PUBKEY:
772
817
                addr = public_key_to_bc_address(x.decode('hex'))
773
818
            else:
774
819
                addr = 'SCRIPT ' + x.encode('hex')
780
825
 
781
826
 
782
827
    def has_address(self, addr):
783
 
        return (addr in self.get_output_addresses()) or (addr in (tx.get("address") for tx in self.inputs))
 
828
        return (addr in self.get_output_addresses()) or (addr in (tx.get("address") for tx in self.inputs()))
784
829
 
785
830
    def as_dict(self):
786
831
        if self.raw is None:
807
852
        # priority must be large enough for free tx
808
853
        threshold = 57600000
809
854
        weight = 0
810
 
        for txin in self.inputs:
 
855
        for txin in self.inputs():
811
856
            age = wallet.get_confirmations(txin["prevout_hash"])[0]
812
857
            weight += txin["value"] * age
813
858
        priority = weight / size
814
859
        print_error(priority, threshold)
815
860
 
816
861
        return priority < threshold
 
862
 
 
863
 
 
864
 
 
865
def tx_from_str(txt):
 
866
    "json or raw hexadecimal"
 
867
    import json
 
868
    txt = txt.strip()
 
869
    try:
 
870
        txt.decode('hex')
 
871
        is_hex = True
 
872
    except:
 
873
        is_hex = False
 
874
    if is_hex:
 
875
        return Transaction(txt)
 
876
    tx_dict = json.loads(str(txt))
 
877
    assert "hex" in tx_dict.keys()
 
878
    tx = Transaction(tx_dict["hex"])
 
879
    return tx