add class BIP32Sequence
authorecdsa <ecdsa@github>
Sat, 2 Mar 2013 22:31:40 +0000 (23:31 +0100)
committerecdsa <ecdsa@github>
Sat, 2 Mar 2013 22:31:40 +0000 (23:31 +0100)
gui/gui_classic.py
lib/bitcoin.py
lib/wallet.py

index b4fda5d..4ea104d 100644 (file)
@@ -1674,7 +1674,7 @@ class ElectrumWindow(QMainWindow):
 
         #self.print_button.setHidden(self.qr_window is None or not self.qr_window.isVisible())
         self.receive_list.setColumnHidden(2, self.qr_window is None or not self.qr_window.isVisible())
-        self.receive_list.setColumnWidth(1, 200)
+        #self.receive_list.setColumnWidth(1, 200)
 
 
     def question(self, msg):
index 4576570..ebfb6da 100644 (file)
@@ -424,13 +424,12 @@ class DeterministicSequence:
             self.is_p2sh = False
 
     @classmethod
-    def from_seed(klass, seed):
+    def mpk_from_seed(klass, seed):
         curve = SECP256k1
         secexp = klass.stretch_key(seed)
         master_private_key = ecdsa.SigningKey.from_secret_exponent( secexp, curve = SECP256k1 )
         master_public_key = master_private_key.get_verifying_key().to_string().encode('hex')
-        self = klass(master_public_key)
-        return self
+        return master_public_key
 
     @classmethod
     def stretch_key(self,seed):
@@ -494,21 +493,57 @@ class DeterministicSequence:
         return True
 
 
-    def add_input_info(self, txin, account, is_change, n):
+    def get_input_info(self, is_change, n):
 
-        txin['electrumKeyID'] = (account, is_change, n) # used by the server to find the key
-        if not self.p2sh:
-            txin['pubkeysig'] = [(None, None)]
-            pk_addr = txin['address']
+        if not self.is_p2sh:
+            pk_addr = self.get_address(is_change, n)
+            redeemScript = None
         else:
             pubkey1 = self.get_pubkey(n, is_change)
             pubkey2 = self.get_pubkey2(n, is_change)
             pk_addr = public_key_to_bc_address( pubkey1.decode('hex') ) # we need to return that address to get the right private key
-            txin['redeemScript'] = Transaction.multisig_script([pubkey1, pubkey2], 2)['redeemScript']
-        return pk_addr
+            redeemScript = Transaction.multisig_script([pubkey1, pubkey2], 2)['redeemScript']
+
+        return pk_addr, redeemScript
+
 
 
 
+class BIP32Sequence:
+
+    def __init__(self, mpkc, mpkc2 = None):
+        self.master_public_key, self.master_chain = mpkc
+        if mpkc2:
+            self.master_public_key2, self.master_chain2 = mpkc2
+            self.is_p2sh = True
+        else:
+            self.is_p2sh = False
+    
+    @classmethod
+    def mpk_from_seed(klass, seed):
+        master_secret, master_chain, master_public_key, master_public_key_compressed = bip32_init(seed)
+        return master_public_key, master_chain
+
+    def get_pubkey(self, sequence):
+        K = self.master_public_key
+        chain = self.mchain
+        for i in sequence:
+            K, K_compressed, chain = CKD_prime(K, chain, i)
+        return K_compressed
+
+    def get_address(self, sequence):
+        return hash_160_to_bc_address(hash_160(self.get_pubkey(sequence)))
+
+    def get_private_key(self, seed, sequence):
+        k = self.master_secret
+        chain = self.master_chain
+        for i in sequence:
+            k, k_compressed, chain = CKD(k, chain, i)
+        return SecretToASecret(k0, True)
+
+    def check_seed(self, seed):
+        master_secret, master_chain, master_public_key, master_public_key_compressed = bip32_init(seed)
+        assert self.master_public_key == master_public_key
 
 ################################## transactions
 
@@ -798,11 +833,11 @@ class Transaction:
             if self.input_info:
                 out['input_info'] = json.dumps(self.input_info).replace(' ','')
 
-
-        print "out", out
         return out
 
 
+
+
 def test_bip32():
     seed = "ff000000000000000000000000000000".decode('hex')
     master_secret, master_chain, master_public_key, master_public_key_compressed = bip32_init(seed)
index 958a911..5d577d5 100644 (file)
@@ -93,9 +93,10 @@ class Wallet:
         self.tx_height             = config.get('tx_height',{})
         self.requested_amounts     = config.get('requested_amounts',{}) 
         self.accounts              = config.get('accounts', {})   # this should not include public keys
-        self.sequences = {}
 
+        self.sequences = {}
         self.sequences[0] = DeterministicSequence(self.config.get('master_public_key'))
+
         if self.accounts.get(0) is None:
             self.accounts[0] = { 0:[], 1:[], 'name':'Main account' }
 
@@ -188,17 +189,12 @@ class Wallet:
         self.config.set_key('seed', self.seed, True)
         self.config.set_key('seed_version', self.seed_version, True)
 
-        self.init_main_account(self.seed)
-        
+        mpk = DeterministicSequence.mpk_from_seed(self.seed)
+        self.config.set_key('master_public_key', mpk, True)
+        self.sequences[0] = DeterministicSequence(mpk)
 
-    def init_main_account(self, seed):
-        # public key
-        sequence = DeterministicSequence.from_seed(seed)
         self.accounts[0] = { 0:[], 1:[], 'name':'Main account' }
-        self.sequences[0] = sequence
         self.config.set_key('accounts', self.accounts, True)
-        mpk = sequence.master_public_key
-        self.config.set_key('master_public_key', mpk, True)
 
 
 
@@ -330,7 +326,7 @@ class Wallet:
 
     def get_new_address(self, account, for_change, n):
         return self.sequences[account].get_address(for_change, n)
-        print_msg( address )
+        print address
         return address
 
     def change_gap_limit(self, value):
@@ -790,12 +786,13 @@ class Wallet:
         for i in range(len(tx.inputs)):
             txin = tx.inputs[i]
             account, is_change, n = self.get_address_index(txin['address'])
-            pk_addr = self.sequences[account].add_input_info(txin, account, is_change, n)
+            pk_addr, redeemScript = self.sequences[account].get_input_info(is_change, n)
+            txin['redeemScript'] = redeemScript
+            txin['electrumKeyID'] = (account, is_change, n) # used by the server to find the key
             pk_addresses.append(pk_addr)
 
         # get all private keys at once.
         private_keys = self.get_private_keys(pk_addresses, password)
-        print "private keys", private_keys
         tx.sign(private_keys)
 
         for address, x in outputs: