コード例 #1
0
ファイル: test_multisig.py プロジェクト: oktoshi/encompass
    def test_p2sh_address_creation(self):
        x1_first_btc_key = bip32_public_derivation(self.wallet.master_public_keys.get("x1/"), "", "/0/0/0")
        x2_first_btc_key = bip32_public_derivation(self.wallet.master_public_keys.get("x2/"), "", "/0/0/0")
        x_pubkeys = [x1_first_btc_key, x2_first_btc_key]
        raw_pubkeys = map( lambda x: deserialize_xkey(x)[4], x_pubkeys )
        pubkeys = map( lambda x: x.encode('hex'), raw_pubkeys )

        # Compare redeem script to manually calculated one
        redeem_script = Transaction.multisig_script(sorted(pubkeys), 2)
        self.assertEqual('522102ee780aa224c9fe54caff984205077b7cca08ced3188a3f3c639d83deda6b9a592103124429ddbed55593d0abea0d0d3d283eca4546e40017b2945f4666c561b494ba52ae',
            redeem_script)

        p2sh_addr = hash_160_to_bc_address( hash_160(redeem_script.decode('hex')), self.wallet.active_chain.p2sh_version )
        self.assertEqual('3MqemPAHZDGLr537QBvU7i4dRFY3Xvad7X', p2sh_addr)

        # switch chains
        self._switch_chain("MZC")
        x1_first_mzc_key = bip32_public_derivation(self.wallet.master_public_keys.get("x1/"), "", "/13/0/0")
        x2_first_mzc_key = bip32_public_derivation(self.wallet.master_public_keys.get("x2/"), "", "/13/0/0")
        x_pubkeys = [x1_first_mzc_key, x2_first_mzc_key]
        raw_pubkeys = map( lambda x: deserialize_xkey(x)[4], x_pubkeys )
        pubkeys = map( lambda x: x.encode('hex'), raw_pubkeys )

        # Compare redeem script to manually calculated one
        redeem_script = Transaction.multisig_script(sorted(pubkeys), 2)
        self.assertEqual('5221027bdb7f5c42096580442e63235434bcc9ddf9689bbeb917705cd0edf9c6e264292102919725862f59a43274443ea11d7a8e25c15147213dcb6186c24d8629d37d6d8d52ae',
            redeem_script)

        p2sh_addr = hash_160_to_bc_address( hash_160(redeem_script.decode('hex')), self.wallet.active_chain.p2sh_version )
        self.assertEqual('4jjXnsGuWLH3YgnagWH12kK7HjDtsBv8SQ', p2sh_addr)
コード例 #2
0
 def createTransaction(self, password, destList):
     """Create a new transaction and send it to the RelayNode
        destList is a list of tuples
        Each tuples is like : (str_address, value)
        The last transaction is the rest of the wallet send to the new user address
     """
     self.checkUpdate()
     newAddr = Address()
     newAddr.encryptPrivateKey(password)
     total = sum([i[1] for i in destList])
     if total <= self.count:
         destList.append((str(newAddr), (self.count - total)))
         transac = Transaction(self.addr.public(), destList)
         self.addr.decryptPrivateKey(password)
         transac.sign(self.addr)
         debug('valid: ' + ('True' if transac.is_signed() else 'False'))
         self.addr.encryptPrivateKey(password)
         if not self.relay.submit_transaction(transac):
             return False
         self.addrList.append(newAddr)
         self.addr = newAddr
         add_address(self.user_ID, self.addr, len(self.addrList) - 1)
         return True
     else:
         return False
コード例 #3
0
ファイル: test_transaction.py プロジェクト: Kefkius/scallop
    def test_deserialize(self):
        tx = Transaction(self.coinstake_tx)
        tx.deserialize()

        self.assertEquals(tx.output_value(), 1437000000)
        self.assertEquals(tx.version, 2)
        self.assertEquals(tx.time, 1430932848)
        self.assertEquals(tx.clamspeech, 'https://Just-Dice.com')
コード例 #4
0
ファイル: handlers.py プロジェクト: expl0si0nn/small_twitter
    def handle_request(self, request):
        try:
            request_type = request.get('type')

            if request_type not in self.no_auth_check_handlers:
                username = request.get('auth', {}).get('username')
                token = request.get('auth', {}).get('auth_token')
                if not username or not token:
                    return construct_result(400, 'Bad request')

                with Transaction() as tr:
                    try:
                        user = User.read_by_name(tr.cursor, username)
                    except ItemNotFoundError:
                        return construct_result(404, 'User not found')

                if not self.auth_handler.verify_auth_token(user.user_id, token):
                    return construct_result(403, 'Bad auth token, you should sign in')

                self.context['user_id'] = user.user_id

            return self.type_to_handler.get(request_type, lambda _: construct_result(400, 'Bad request'))(request)
        except KeyboardInterrupt:
            raise
        except Exception as e:
            logging.exception('Unhandled exception during request handling occured: {}'.format(e))
            return construct_result(500, 'Error occured')
コード例 #5
0
ファイル: client_cli.py プロジェクト: axtux/CryptoCurrency
def transfer(bc, relay, from_addr, to_addr, amount):
    f = get_address(from_addr)
    if f is None:
        exit('no address '+str(from_addr)+' in database')
    
    total = bc.get_amount_of_address(f)
    if total < amount:
        exit('not enough money for this transfer')
    
    pwd = getpass.getpass()
    while not f.decryptPrivateKey(pwd):
        print('Invalid password')
        pwd = getpass.getpass()
    
    receivers = [(to_addr, amount)]
    if total > amount:
        new = Address()
        new.encryptPrivateKey(pwd)
        db.add_address('client', new, 0)
        print('created new address '+str(new)+' to receive remaining funds')
        receivers.append((str(new), total - amount))
    t = Transaction(f, receivers)
    if relay.submit_transaction(t):
        print('transaction sent to the network')
    else:
        print('error sending transaction')
コード例 #6
0
    def __init__(self, seed, *args):
        self.seed = seed
        self.wallet = Wallet(utils.hash(str(self.seed)))
        self.neighbours = set()
        self.DAG = {}

        root_transaction = Transaction('0000', 'root', 25000000000)
        self.attach_transaction(root_transaction, ['root'])
コード例 #7
0
ファイル: spender.py プロジェクト: gustavonalle/bfs
    def create_tx(self):
        tx = Transaction(version=self.tx_version,
                         sig_hash_type=self.sig_hash_type,
                         sig_hash_type_pre_image=self.sig_hash_type_pre_image,
                         sign_style=self.sign_type)
        keys = []
        for utxo in self.utxos:
            pub_key = utxo.private_key.create_pub_key()
            keys.append(KeyPair(utxo.private_key, pub_key))
            tx_input = TransactionInput(utxo.tx_hash,
                                        utxo.index,
                                        utxo.address,
                                        get_spend_type(utxo.address),
                                        prev_amount=utxo.amount_btc,
                                        pub_key=pub_key)
            tx.add_inputs(tx_input)

        for destination in self.destinations:
            tx_output = TransactionOutput(
                btc_to_satoshis(destination.amount_btc), destination.address,
                get_spend_type(destination.address))
            tx.add_outputs(tx_output)

        signed = tx.sign(*keys)
        return signed.serialize()
コード例 #8
0
    def make_transaction(self, receiving_addr, value):
        '''
            1. Pick at least two transactions in Tangle to confirm
            2. Check picked transactions for conflict
            3. Approve non conflicting transactions
            4. Perform proof of work
            5. Send transaction to tangle 
        '''
        confirmed_transactions = self.confirm_transactions()

        if len(confirmed_transactions) >= 2:
            proof_of_work = self.proof_of_work(''.join(confirmed_transactions))
            new_transaction = Transaction(self.wallet.generate_address(),
                                          receiving_addr, value)
            new_transaction.pow = proof_of_work
            return self.attach_transaction(new_transaction,
                                           confirmed_transactions)

        return {'msg': 'transaction failed'}
コード例 #9
0
def construct_follows_list_response(follows, followers_mode=False):
    res = []
    for follow in follows:
        with Transaction() as tr:
            try:
                user_id = follow.user_id if not followers_mode else follow.follower_id
                res.append(User.read_by_pk(tr.cursor, user_id).username)
            except ItemNotFoundError:
                continue
    return res
コード例 #10
0
ファイル: handlers.py プロジェクト: expl0si0nn/small_twitter
    def handle_post(self, request):
        text = request.get('text')
        if not text:
            return construct_result(400, 'Bad request')

        ts = int(time.time())

        with Transaction() as tr:
            Post(self.context['user_id'], None, text, ts).create_me(tr.cursor)

        return construct_result()
コード例 #11
0
 def post_transaction(self, json):
     t = Transaction.fromJson(json)
     if t is None:
         debug('JSON error')
         self.no_response(400)  # Bad Request
     elif not t.is_valid(self.server.blockchain):
         debug('invalid blockchain transaction')
         self.no_response(400)  # Bad Request
     else:
         self.server.transactions.append(t)
         self.no_response(200)  # OK
         self.broadcast_transaction(t)
コード例 #12
0
ファイル: blockchain.py プロジェクト: ptr5000/dummycoin
    def test_pending_transactions(self):
        receiver = generate_key()

        tx = Transaction(None, txtype=TxType.COINBASE)
        tx.add_out(10, receiver.publickey())

        blockchain = Blockchain()
        blockchain.add(tx)

        pending_tx = blockchain.get_pending_transactions()

        self.assertEqual(len(filter(lambda x: tx.hash, pending_tx)), 1)

        miner = Miner(blockchain)
        miner.reward_addr = receiver.publickey()
        newb = miner._mine()

        pending_tx = blockchain.get_pending_transactions()

        self.assertEqual(len(filter(lambda x: tx.hash, pending_tx)), 0)
        self.assertEqual(len(filter(lambda x: tx.hash, newb.transactions)), 2)
コード例 #13
0
ファイル: tangle.py プロジェクト: aliteke/Tango
    def __init__(self, isgenesis=True, *args):
        # represent the "sites" containing transactions
        # self.tngl = nx.DiGraph()

        if isgenesis:
            self.DAG = OrderedDict()
            genesis_tx = Transaction('genesis_address', 'genesis_address',
                                     21000000)
            genesis_tx_key = self.attach_transaction(genesis_tx,
                                                     ['genesis_tx'])

            founding_txA = Transaction('genesis_address', 'founderA_address',
                                       7000000)
            self.attach_transaction(founding_txA, [genesis_tx_key])

            founding_txB = Transaction('genesis_address', 'founderB_address',
                                       7000000)
            self.attach_transaction(founding_txB, [genesis_tx_key])

        else:
            print "[+] Genesis tangle is already done, connect and sync from neighbours"
コード例 #14
0
def construct_posts_list_response(posts):
    res = []
    for post in posts:
        post_dict = post.to_dict()
        with Transaction() as tr:
            try:
                post_dict['username'] = User.read_by_pk(
                    tr.cursor, post_dict.pop('user_id')).username
            except ItemNotFoundError:
                continue
        res.append(post_dict)
    return res
コード例 #15
0
ファイル: index.py プロジェクト: stevepryde/stevecoin
def transaction_submit():
    """Submit a new transaction to the pool."""
    try:
        if not request.json:
            abort(400, "Invalid transaction")

        tx = Transaction.deserialise_dict(request.json)
        tx.validate(CHAIN.q)
        CHAIN.q.add_transaction_to_pending(tx)
    except TransactionValidationError as exc:
        abort(400, "Invalid transaction: {}".format(exc))
    except BlockChainError:
        abort(500, "Blockchain error")
コード例 #16
0
ファイル: handlers.py プロジェクト: expl0si0nn/small_twitter
    def handle_get_user_posts(self, request):
        username = request.get('username')
        if not username:
            return construct_result(400, 'Bad request')

        with Transaction() as tr:
            try:
                user = User.read_by_name(tr.cursor, username)
            except ItemNotFoundError:
                return construct_result(404, 'User not found')

            posts = Post.get_user_posts(tr.cursor, user.user_id)

        return construct_result(200, construct_posts_list_response(posts))
コード例 #17
0
ファイル: handlers.py プロジェクト: expl0si0nn/small_twitter
    def handle_get_following_users(self, request):
        username = request.get('username')
        if not username:
            return construct_result(400, 'Bad request')

        with Transaction() as tr:
            try:
                user = User.read_by_name(tr.cursor, username)
            except ItemNotFoundError:
                return construct_result(404, 'User not found')

            follows = Follow.get_following_users(tr.cursor, user.user_id)

        return construct_result(200, construct_follows_list_response(follows, followers_mode=True))
コード例 #18
0
ファイル: handlers.py プロジェクト: expl0si0nn/small_twitter
    def handle_follow(self, request):
        username_to_follow = request.get('username_to_follow')
        if not username_to_follow:
            return construct_result(400, 'Bad request')

        with Transaction() as tr:
            try:
                user_to_follow = User.read_by_name(tr.cursor, username_to_follow)
            except ItemNotFoundError:
                return construct_result(404, 'User not found')

            Follow(None, user_to_follow.user_id, self.context['user_id']).create_me(tr.cursor)

        return construct_result()
コード例 #19
0
ファイル: block.py プロジェクト: axtux/CryptoCurrency
 def fromJson(json_data):
     try:
         data = json.loads(json_data)
         b = Block(data["previous_hash"], data["miner_address"])
         ts = []
         for t in data["transactions"]:
             ts.append(Transaction.fromJson(t))
         b.set_transactions(ts)
         b.set_proof(data["proof"])
         return b
     # JSON ValueError for decode
     # KeyError if no accessed key
     except (ValueError, KeyError, TypeError):
         return None
コード例 #20
0
def maketx(inputs, outputs):
    """
    Make a transaction from the given inputs and outputs list. Saves the serialized tx to `alltxes` and returns the key (its txid).
    """
    tx = Transaction.from_io(inputs, outputs)
    txid = tx.txid()
    raw = str(tx)  # ensure we work with serialized version.
    #txid = Transaction(raw).txid() # re-deserialize to make sure we get the right txid

    alltxes[txid] = raw

    print("Generated %.10s... (%d -> %d)" % (txid, len(inputs), len(outputs)))

    return txid
コード例 #21
0
ファイル: handlers.py プロジェクト: expl0si0nn/small_twitter
    def handle_like(self, request):
        post_id = request.get('post_id')
        if not post_id:
            return construct_result(400, 'Bad request')

        with Transaction() as tr:
            try:
                post = Post.read_by_pk(tr.cursor, post_id)
            except ItemNotFoundError:
                return construct_result(404, 'Post not found')

            post.likes += 1
            post.update_me(tr.cursor)

        return construct_result()
コード例 #22
0
ファイル: handlers.py プロジェクト: expl0si0nn/small_twitter
    def handle_signin(self, request):
        username = request.get('username')
        password = request.get('password')
        if not username or not password:
            return construct_result(400, 'Bad request')

        with Transaction() as tr:
            try:
                user = User.read_by_name(tr.cursor, username)
            except ItemNotFoundError:
                return construct_result(404, 'User not found')

            if not self.auth_handler.verify_password(password, user.password_key):
                return construct_result(400, 'Bad password')

        return construct_result(200, {'auth_token': self.auth_handler.get_auth_token(user.user_id)})
コード例 #23
0
 def get_transactions(self):
     """send GET request to relay/transactions/ and parse it
     """
     r = get_request(self.url+'transactions/')
     if r is None:
         return None
     if not r.status_code == 200:
         return None
     try:
         json_ts = r.json()
     except ValueError:
         return None
     ts = []
     for json in json_ts:
         t = Transaction.fromJson(json)
         if not t is None:
             ts.append(t)
     return ts
コード例 #24
0
ファイル: handlers.py プロジェクト: expl0si0nn/small_twitter
    def handle_signup(self, request):
        username = request.get('username')
        password = request.get('password')
        if not username or not password:
            return construct_result(400, 'Bad request')

        with Transaction() as tr:
            no_users = False
            try:
                user = User.read_by_name(tr.cursor, username)
            except ItemNotFoundError:
                no_users = True

            if not no_users:
                return construct_result(400, 'User already exists')

            User(None, username, self.auth_handler.get_password_key(password)).create_me(tr.cursor)

        return construct_result()
コード例 #25
0
ファイル: handlers.py プロジェクト: expl0si0nn/small_twitter
    def handle_admin_info(self, request):
        with Transaction() as tr:
            try:
                user = User.read_by_pk(tr.cursor, self.context['user_id'])
            except ItemNotFoundError:
                return construct_result(404, 'User not found')

            if not user.is_admin:
                return construct_result(403, 'Access denied')

            users = User.read_all(tr.cursor)
            posts = Post.read_all(tr.cursor)
            follows = Follow.read_all(tr.cursor)

        return construct_result(
            200,
            {
                'users': [user.to_dict() for user in users],
                'posts': [post.to_dict() for post in posts],
                'folows': [follow.to_dict() for follow in follows],
            }
        )
コード例 #26
0
    def create_new_block(self):
        """
        Create a fresh new block that contains all valid
        pending transactions.
        """
        newb = Block(self.blockchain.top().hash)
        newb.index = self.blockchain.top().index + 1

        newb.transactions.extend(self.blockchain.get_pending_transactions())

        tx = Transaction(None, txtype=TxType.COINBASE)
        tx.add_out(MINING_REWARD, self.reward_addr)
        tx.finalize()

        newb.transactions.append(tx)

        return newb
コード例 #27
0
ファイル: blockchain.py プロジェクト: ptr5000/dummycoin
    def _test_fraudulent_tx(self, victim, blockchain):
        """
        Try transaction from somebody else's "wallet"
        """

        miner_key = generate_key()
        perpetrator = generate_key()

        utxo = blockchain.scan_unspent_transactions(victim.publickey())

        perpetrator_owns = blockchain.scan_unspent_transactions(
            perpetrator.publickey())
        self.assertEqual(len(perpetrator_owns), 0)  # Sanity check

        # Let's handcraft tx that tries to steal victim's coins.
        tx = Transaction(perpetrator)  # Sign it with random key

        utxo = blockchain.scan_unspent_transactions(
            victim.publickey())  # Get victim's utxo

        debit = sum(map(lambda x: x['value'], utxo))

        for credit in utxo:
            tx.add_in(credit['hash'], sign(perpetrator, credit['hash']),
                      victim.publickey(), credit['value'])

        tx.add_out(debit, perpetrator.publickey())

        try:
            blockchain.add(tx)
            self.fail("Should've thrown UnauthorizedTxException")
        except UnauthorizedTxException:
            pass

        miner = Miner(blockchain)
        miner.reward_addr = miner_key.publickey()
        _ = miner._mine()

        perpetrator_owns = blockchain.scan_unspent_transactions(
            perpetrator.publickey())

        # Should own nothing. This tx should've failed.
        self.assertEqual(len(perpetrator_owns), 0)
コード例 #28
0
    def test_sending_between_p2wsh_2of3_and_p2wsh_p2sh_2of2(self, mock_write):
        wallet1a = WalletIntegrityHelper.create_multisig_wallet(
            keystore.from_seed(
                'bitter grass shiver impose acquire brush forget axis eager alone wine silver',
                '', True),
            keystore.from_xpub(
                'Vpub5fcdcgEwTJmbmqAktuK8Kyq92fMf7sWkcP6oqAii2tG47dNbfkGEGUbfS9NuZaRywLkHE6EmUksrqo32ZL3ouLN1HTar6oRiHpDzKMAF1tf'
            ),
            keystore.from_xpub(
                'Vpub5fjkKyYnvSS4wBuakWTkNvZDaBM2vQ1MeXWq368VJHNr2eT8efqhpmZ6UUkb7s2dwCXv2Vuggjdhk4vZVyiAQTwUftvff73XcUGq2NQmWra'
            ),
            gap_limit=2)
        wallet1b = WalletIntegrityHelper.create_multisig_wallet(
            keystore.from_seed(
                'snow nest raise royal more walk demise rotate smooth spirit canyon gun',
                '', True),
            keystore.from_xpub(
                'Vpub5fjkKyYnvSS4wBuakWTkNvZDaBM2vQ1MeXWq368VJHNr2eT8efqhpmZ6UUkb7s2dwCXv2Vuggjdhk4vZVyiAQTwUftvff73XcUGq2NQmWra'
            ),
            keystore.from_xpub(
                'Vpub5gSKXzxK7FeKQedu2q1z9oJWxqvX72AArW3HSWpEhc8othDH8xMDu28gr7gf17sp492BuJod8Tn7anjvJrKpETwqnQqX7CS8fcYyUtedEMk'
            ),
            gap_limit=2)
        # ^ third seed: hedgehog sunset update estate number jungle amount piano friend donate upper wool
        wallet2a = WalletIntegrityHelper.create_multisig_wallet(
            # bip39: finish seminar arrange erosion sunny coil insane together pretty lunch lunch rose, der: m/1234'/1'/0', p2wsh-p2sh multisig
            keystore.from_xprv(
                'Uprv9CvELvByqm8k2dpecJVjgLMX1z5DufEjY4fBC5YvdGF5WjGCa7GVJJ2fYni1tyuF7Hw83E6W2ZBjAhaFLZv2ri3rEsubkCd5avg4EHKoDBN'
            ),
            keystore.from_xpub(
                'Upub5Qb8ik4Cnu8g97KLXKgVXHqY6tH8emQvqtBncjSKsyfTZuorPtTZgX7ovKKZHuuVGBVd1MTTBkWez1XXt2weN1sWBz6SfgRPQYEkNgz81QF'
            ),
            gap_limit=2)
        wallet2b = WalletIntegrityHelper.create_multisig_wallet(
            # bip39: square page wood spy oil story rebel give milk screen slide shuffle, der: m/1234'/1'/0', p2wsh-p2sh multisig
            keystore.from_xprv(
                'Uprv9BbnKEXJxXaNvdEsRJ9VA9toYrSeFJh5UfGBpM2iKe8Uh7UhrM9K8ioL53s8gvCoGfirHHaqpABDAE7VUNw8LNU1DMJKVoWyeNKu9XcDC19'
            ),
            keystore.from_xpub(
                'Upub5RuakRisg8h3F7u7iL2k3UJFa1uiK7xauHamzTxYBbn4PXbM7eajr6M9Q2VCr6cVGhfhqWQqxnABvtSATuVM1xzxk4nA189jJwzaMn1QX7V'
            ),
            gap_limit=2)

        # bootstrap wallet1
        funding_tx = Transaction(
            '01000000000101a41aae475d026c9255200082c7fad26dc47771275b0afba238dccda98a597bd20000000000fdffffff02400d0300000000002200203c43ac80d6e3015cf378bf6bac0c22456723d6050bef324ec641e7762440c63c9dcd410000000000160014824626055515f3ed1d2cfc9152d2e70685c71e8f02483045022100b9f39fad57d07ce1e18251424034f21f10f20e59931041b5167ae343ce973cf602200fefb727fa0ffd25b353f1bcdae2395898fe407b692c62f5885afbf52fa06f5701210301a28f68511ace43114b674371257bb599fd2c686c4b19544870b1799c954b40e9c11300'
        )
        funding_txid = funding_tx.txid()
        funding_output_value = 200000
        self.assertEqual(
            'd2bd6c9d332db8e2c50aa521cd50f963fba214645aab2f7556e061a412103e21',
            funding_txid)
        wallet1a.receive_tx_callback(funding_txid, funding_tx,
                                     TX_HEIGHT_UNCONFIRMED)

        # wallet1 -> wallet2
        outputs = [(bitcoin.TYPE_ADDRESS, wallet2a.get_receiving_address(),
                    165000)]
        tx = wallet1a.mktx(outputs=outputs,
                           password=None,
                           config=self.config,
                           fee=5000)
        tx = Transaction(
            tx.serialize())  # simulates moving partial txn between cosigners
        self.assertFalse(tx.is_complete())
        wallet1b.sign_transaction(tx, password=None)

        self.assertTrue(tx.is_complete())
        self.assertTrue(tx.is_segwit())
        self.assertEqual(1, len(tx.inputs()))
        tx_copy = Transaction(tx.serialize())
        self.assertEqual(wallet1a.is_mine(tx.inputs()[0]['address']),
                         wallet1a.is_mine(tx_copy.inputs()[0]['address']))
        self.assertTrue(wallet1a.is_mine(tx.inputs()[0]['address']))
        self.assertEqual(wallet1a.txin_type, tx_copy.inputs()[0]['type'])
        self.assertEqual(tx.wtxid(), tx_copy.wtxid())
        self.assertEqual(
            '6e9c3cd8788bdb970a124ea06136d52bc01cec4f9b1e217627d5e90ebe77d049',
            tx_copy.txid())

        wallet1a.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)
        wallet2a.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)

        # wallet2 -> wallet1
        outputs = [(bitcoin.TYPE_ADDRESS, wallet1a.get_receiving_address(),
                    100000)]
        tx = wallet2a.mktx(outputs=outputs,
                           password=None,
                           config=self.config,
                           fee=5000)
        tx = Transaction(
            tx.serialize())  # simulates moving partial txn between cosigners
        self.assertFalse(tx.is_complete())
        wallet2b.sign_transaction(tx, password=None)

        self.assertTrue(tx.is_complete())
        self.assertTrue(tx.is_segwit())
        self.assertEqual(1, len(tx.inputs()))
        tx_copy = Transaction(tx.serialize())
        self.assertEqual(wallet2a.is_mine(tx.inputs()[0]['address']),
                         wallet2a.is_mine(tx_copy.inputs()[0]['address']))
        self.assertTrue(wallet2a.is_mine(tx.inputs()[0]['address']))
        self.assertEqual(wallet2a.txin_type, tx_copy.inputs()[0]['type'])
        self.assertEqual(tx.wtxid(), tx_copy.wtxid())
        self.assertEqual(
            '84b0dcb43022385f7a10e2710e5625a2be3cd6e390387b6100b55500d5eea8f6',
            tx_copy.txid())

        wallet1a.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)
        wallet2a.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)

        # wallet level checks
        self.assertEqual((0, funding_output_value - 165000 - 5000 + 100000, 0),
                         wallet1a.get_balance())
        self.assertEqual((0, 165000 - 5000 - 100000, 0),
                         wallet2a.get_balance())
コード例 #29
0
    def test_sending_between_p2sh_2of3_and_uncompressed_p2pkh(
            self, mock_write):
        wallet1a = WalletIntegrityHelper.create_multisig_wallet(
            keystore.from_seed(
                'blast uniform dragon fiscal ensure vast young utility dinosaur abandon rookie sure',
                '', True),
            keystore.from_xpub(
                'tpubD6NzVbkrYhZ4YTPEgwk4zzr8wyo7pXGmbbVUnfYNtx6SgAMF5q3LN3Kch58P9hxGNsTmP7Dn49nnrmpE6upoRb1Xojg12FGLuLHkVpVtS44'
            ),
            keystore.from_xpub(
                'tpubD6NzVbkrYhZ4XJzYkhsCbDCcZRmDAKSD7bXi9mdCni7acVt45fxbTVZyU6jRGh29ULKTjoapkfFsSJvQHitcVKbQgzgkkYsAmaovcro7Mhf'
            ),
            gap_limit=2)
        wallet1b = WalletIntegrityHelper.create_multisig_wallet(
            keystore.from_seed(
                'cycle rocket west magnet parrot shuffle foot correct salt library feed song',
                '', True),
            keystore.from_xpub(
                'tpubD6NzVbkrYhZ4YTPEgwk4zzr8wyo7pXGmbbVUnfYNtx6SgAMF5q3LN3Kch58P9hxGNsTmP7Dn49nnrmpE6upoRb1Xojg12FGLuLHkVpVtS44'
            ),
            keystore.from_xpub(
                'tpubD6NzVbkrYhZ4YARFMEZPckrqJkw59GZD1PXtQnw14ukvWDofR7Z1HMeSCxfYEZVvg4VdZ8zGok5VxHwdrLqew5cMdQntWc5mT7mh1CSgrnX'
            ),
            gap_limit=2)
        # ^ third seed: ghost into match ivory badge robot record tackle radar elbow traffic loud
        wallet2 = self.create_standard_wallet_from_seed(
            'powerful random nobody notice nothing important anyway look away hidden message over'
        )

        # bootstrap wallet1
        funding_tx = Transaction(
            '010000000001014121f99dc02f0364d2dab3d08905ff4c36fc76c55437fd90b769c35cc18618280100000000fdffffff02d4c22d00000000001600143fd1bc5d32245850c8cb5be5b09c73ccbb9a0f75001bb7000000000017a91480c2353f6a7bc3c71e99e062655b19adb3dd2e4887024830450221008781c78df0c9d4b5ea057333195d5d76bc29494d773f14fa80e27d2f288b2c360220762531614799b6f0fb8d539b18cb5232ab4253dd4385435157b28a44ff63810d0121033de77d21926e09efd04047ae2d39dbd3fb9db446e8b7ed53e0f70f9c9478f735dac11300'
        )
        funding_txid = funding_tx.txid()
        funding_output_value = 12000000
        self.assertEqual(
            'b25cd55687c9e528c2cfd546054f35fb6741f7cf32d600f07dfecdf2e1d42071',
            funding_txid)
        wallet1a.receive_tx_callback(funding_txid, funding_tx,
                                     TX_HEIGHT_UNCONFIRMED)

        # wallet1 -> wallet2
        outputs = [(bitcoin.TYPE_ADDRESS, wallet2.get_receiving_address(),
                    370000)]
        tx = wallet1a.mktx(outputs=outputs,
                           password=None,
                           config=self.config,
                           fee=5000)
        tx = Transaction(
            tx.serialize())  # simulates moving partial txn between cosigners
        self.assertFalse(tx.is_complete())
        wallet1b.sign_transaction(tx, password=None)

        self.assertTrue(tx.is_complete())
        self.assertFalse(tx.is_segwit())
        self.assertEqual(1, len(tx.inputs()))
        tx_copy = Transaction(tx.serialize())
        self.assertEqual(wallet1a.is_mine(tx.inputs()[0]['address']),
                         wallet1a.is_mine(tx_copy.inputs()[0]['address']))
        self.assertTrue(wallet1a.is_mine(tx.inputs()[0]['address']))
        self.assertEqual(wallet1a.txin_type, tx_copy.inputs()[0]['type'])
        self.assertEqual(tx.wtxid(), tx_copy.wtxid())
        self.assertEqual(
            '26f3bdd0402e1cff19126244ebe3d32722cef0db507c7229ca8754f5e06ef25d',
            tx_copy.txid())

        wallet1a.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)
        wallet2.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)

        # wallet2 -> wallet1
        outputs = [(bitcoin.TYPE_ADDRESS, wallet1a.get_receiving_address(),
                    100000)]
        tx = wallet2.mktx(outputs=outputs,
                          password=None,
                          config=self.config,
                          fee=5000)

        self.assertTrue(tx.is_complete())
        self.assertFalse(tx.is_segwit())
        self.assertEqual(1, len(tx.inputs()))
        tx_copy = Transaction(tx.serialize())
        self.assertEqual(wallet2.is_mine(tx.inputs()[0]['address']),
                         wallet2.is_mine(tx_copy.inputs()[0]['address']))
        self.assertTrue(wallet2.is_mine(tx.inputs()[0]['address']))
        self.assertEqual(wallet2.txin_type, tx_copy.inputs()[0]['type'])
        self.assertEqual(tx.wtxid(), tx_copy.wtxid())
        self.assertEqual(
            'c573b3f8464a4ed40dfc79d0889a780f44e917beef7a75883b2427c2987f3e95',
            tx_copy.txid())

        wallet1a.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)
        wallet2.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)

        # wallet level checks
        self.assertEqual((0, funding_output_value - 370000 - 5000 + 100000, 0),
                         wallet1a.get_balance())
        self.assertEqual((0, 370000 - 5000 - 100000, 0), wallet2.get_balance())
コード例 #30
0
    def test_sending_between_p2wpkh_and_compressed_p2pkh(self, mock_write):
        wallet1 = self.create_standard_wallet_from_seed(
            'bitter grass shiver impose acquire brush forget axis eager alone wine silver'
        )
        wallet2 = self.create_standard_wallet_from_seed(
            'cycle rocket west magnet parrot shuffle foot correct salt library feed song'
        )

        # bootstrap wallet1
        funding_tx = Transaction(
            '01000000014576dacce264c24d81887642b726f5d64aa7825b21b350c7b75a57f337da6845010000006b483045022100a3f8b6155c71a98ad9986edd6161b20d24fad99b6463c23b463856c0ee54826d02200f606017fd987696ebbe5200daedde922eee264325a184d5bbda965ba5160821012102e5c473c051dae31043c335266d0ef89c1daab2f34d885cc7706b267f3269c609ffffffff0240420f00000000001600148a28bddb7f61864bdcf58b2ad13d5aeb3abc3c42a2ddb90e000000001976a914c384950342cb6f8df55175b48586838b03130fad88ac00000000'
        )
        funding_txid = funding_tx.txid()
        funding_output_value = 1000000
        self.assertEqual(
            'add2535aedcbb5ba79cc2260868bb9e57f328738ca192937f2c92e0e94c19203',
            funding_txid)
        wallet1.receive_tx_callback(funding_txid, funding_tx,
                                    TX_HEIGHT_UNCONFIRMED)

        # wallet1 -> wallet2
        outputs = [(bitcoin.TYPE_ADDRESS, wallet2.get_receiving_address(),
                    250000)]
        tx = wallet1.mktx(outputs=outputs,
                          password=None,
                          config=self.config,
                          fee=5000)

        self.assertTrue(tx.is_complete())
        self.assertTrue(tx.is_segwit())
        self.assertEqual(1, len(tx.inputs()))
        tx_copy = Transaction(tx.serialize())
        self.assertEqual(wallet1.is_mine(tx.inputs()[0]['address']),
                         wallet1.is_mine(tx_copy.inputs()[0]['address']))
        self.assertTrue(wallet1.is_mine(tx.inputs()[0]['address']))
        self.assertEqual(wallet1.txin_type, tx_copy.inputs()[0]['type'])
        self.assertEqual(tx.wtxid(), tx_copy.wtxid())
        self.assertEqual(
            '3c06ae4d9be8226a472b3e7f7c127c7e3016f525d658d26106b80b4c7e3228e2',
            tx_copy.txid())

        wallet1.receive_tx_callback(
            tx.txid(), tx,
            TX_HEIGHT_UNCONFIRMED)  # TX_HEIGHT_UNCONF_PARENT but nvm
        wallet2.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)

        # wallet2 -> wallet1
        outputs = [(bitcoin.TYPE_ADDRESS, wallet1.get_receiving_address(),
                    100000)]
        tx = wallet2.mktx(outputs=outputs,
                          password=None,
                          config=self.config,
                          fee=5000)

        self.assertTrue(tx.is_complete())
        self.assertFalse(tx.is_segwit())
        self.assertEqual(1, len(tx.inputs()))
        tx_copy = Transaction(tx.serialize())
        self.assertEqual(wallet2.is_mine(tx.inputs()[0]['address']),
                         wallet2.is_mine(tx_copy.inputs()[0]['address']))
        self.assertTrue(wallet2.is_mine(tx.inputs()[0]['address']))
        self.assertEqual(wallet2.txin_type, tx_copy.inputs()[0]['type'])
        self.assertEqual(tx.wtxid(), tx_copy.wtxid())
        self.assertEqual(
            '5f25707571eb776bdf14142f9966bf2a681906e0a79501edbb99a972c2ceb972',
            tx_copy.txid())

        wallet1.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)
        wallet2.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)

        # wallet level checks
        self.assertEqual((0, funding_output_value - 250000 - 5000 + 100000, 0),
                         wallet1.get_balance())
        self.assertEqual((0, 250000 - 5000 - 100000, 0), wallet2.get_balance())
コード例 #31
0
ファイル: test_multisig.py プロジェクト: martexcoin/encompass
    def test_transaction(self):

        wallet_keys = {
            'xpub6GDQf5vZmrpQvD4ixNdqHmgSZ76Uo2Cg5isBupnvZpnNbhdRhgdhq9hkfCSKRE31rGfYuXNfZ5gTamFkj1GXt6k87MD1hUn28tuvLHY71Bk':
            'L2FQCaHPwgS4CmAf6bKtbjVWDbcHv42c72by1zLEyLuDrUG22CwM',
            'xpub6GLs33TeHkrLSTJ2uxiMLnuqxCHG9iBFCwjTwyg4EvzyxUi78U1sXxxRPUQfLGNEZRT3yYKEwR39ZbUtofEgcmTLtJdSetnFiQPEwTZRW5y':
            'L1aD1WSA3UGU56sAmjfYVj1rK3fnSzWKj2wTsDTN1DpgUgPVwQCa',
            'xpub6Fc64k9RTc79yD7xErF2yKSdUraGBhGWDt1FomUFVCFg52165LZvvoGL59hebJBGtauFqNL5zMeRgPGV29sfQp6XqoiiD9E53UDatBhFZuk':
            'L25eCRYrDNVNrTZV1XZhmaZti3dVsZz3egm1R7LsPHRdpYuyLYKE'
            #            'xpub6GiSmJrVQC5q2m5cRcZvUgnGUsfeEqi3eEfUTgacnA33G8PAQnJeeMzpNAGUA9JL3goUui7BY52rVPwhmxMALkmFh5ZuwJDKrPv8ERkG3CK': 'L3jUPoR7fUwB9mwfuqqF79mHDpj5rpygQhdWntJ9ShZ9nbyRab5h'
        }

        acc = self.wallet.accounts["0"]
        redeem_script = '53210278a1a7de63493a8c8e0e7f4ebb13fd2a8144db25bb3bc2e5f44127a851a389332102ee780aa224c9fe54caff984205077b7cca08ced3188a3f3c639d83deda6b9a592103124429ddbed55593d0abea0d0d3d283eca4546e40017b2945f4666c561b494ba210312872f0aa80fa1a9bc7df77fa5be310f5441f7bfec798fe19209b04954dec8da54ae'

        coins = [{
            'address': '32SbQbBthcMzRSpCw1ifAXqWviJGH5HKUk',
            'value': 600000,
            'prevout_n': 0,
            'prevout_hash':
            '1111111111111111111111111111111111111111111111111111111111111111',
            'height': 100000,
            'coinbase': 'True'
        }]

        txin = coins[0]

        x_pubkeys = map(lambda x: bip32_public_derivation(x, "", "/0/0/0"),
                        self.wallet.master_public_keys.values())
        pubkeys = map(lambda x: deserialize_xkey(x)[4].encode('hex'),
                      x_pubkeys)

        s = ''.join(map(lambda x: int_to_hex(x, 2), (0, 0)))
        x_pubkeys = map(
            lambda x: 'ff' + DecodeBase58Check(x).encode('hex') + s, x_pubkeys)
        pubkeys, x_pubkeys = zip(*sorted(zip(pubkeys, x_pubkeys)))
        txin['pubkeys'] = list(pubkeys)
        txin['x_pubkeys'] = list(x_pubkeys)
        txin['signatures'] = [None] * len(pubkeys)
        txin['redeemScript'] = redeem_script
        txin['num_sig'] = acc.multisig_m

        outputs = [('address', '1PyXgL1qmZPuxcVi9CcguQb3v7WUvQZBud', 500000)]
        inputs = []
        tx = Transaction(inputs, outputs)
        tx.add_input(txin)
        self.wallet.sign_transaction(tx, "secret")

        #
        ins = tx.inputs_to_sign()
        keypairs = {}
        sec = None
        for innard in ins:
            # this is easier than the commented loop below
            in_xpub, _ = BIP32_Account.parse_xpubkey(innard)
            if wallet_keys.get(in_xpub):
                keypairs[innard] = wallet_keys[in_xpub]
            # ...


#            in_xpub, in_seq = BIP32_Account.parse_xpubkey(innard)
#            sec = None
#            for k, vaccount in self.wallet.accounts.items():
#                acc_v = vaccount.get_master_pubkeys()[0]
#                acc_xpub = bip32_public_derivation(acc_v, "", "/0/0")
#                if in_xpub == acc_xpub:
#                    pk = vaccount.get_private_key(in_seq, self.wallet, "secret")
#                    sec = pk[0]

#            if sec:
#                keypairs [ innard ] = sec

        if keypairs:
            tx.sign(keypairs)
        self.assertEqual(
            '0100000001111111111111111111111111111111111111111111111111111111111111111100000000fd6701004730440220774e80fda89895d8bf3ac39c38f39456d31c1e857dc1c77c000f4de6c3de15fe02207b6d13b5ba17eadeb607f3ca56f693a0b777dae668584cefec0910a8bc90869a0147304402205e80562254972f873b5b59b1cdc81e422c7a2959d8868e5a54238fbfdf6f107002200204eef593812453ae2c22334c409f9ef25523cf9619399eb2d3c249673443dc01483045022100a81e69796aa5e5ae0d8924047e3c81a8dd64dfbc791caba6728ac7820aa114da022060b85875fd58223b7c61ef45fac2567a9f76934f947e4d03d927f5b078e1fb45014c8b53210278a1a7de63493a8c8e0e7f4ebb13fd2a8144db25bb3bc2e5f44127a851a389332102ee780aa224c9fe54caff984205077b7cca08ced3188a3f3c639d83deda6b9a592103124429ddbed55593d0abea0d0d3d283eca4546e40017b2945f4666c561b494ba210312872f0aa80fa1a9bc7df77fa5be310f5441f7bfec798fe19209b04954dec8da54aeffffffff0120a10700000000001976a914fc03ab7c28d17349f084f7cadde4dafc356918d388ac00000000',
            str(tx))

        ###########
        #
        serialized_tx = str(tx)
        tx2 = Transaction.deserialize(serialized_tx,
                                      active_chain=self.wallet.active_chain)
        self.assertEquals(4, len(tx2.inputs[0]['x_pubkeys']))
        self.assertEquals(3, tx2.inputs[0]['num_sig'])
コード例 #32
0
ファイル: test_transaction.py プロジェクト: Kefkius/scallop
    def test_coinstake_marker(self):
        raw_tx = '02000000704d4a55010000000000000000000000000000000000000000000000000000000000000000ffffffff04033df406ffffffff010000000000000000000000000000'
        tx = Transaction(raw_tx)
        tx.deserialize()

        self.assertEquals(tx.inputs[0]['is_coinbase'], True)
コード例 #33
0
ファイル: test_transaction.py プロジェクト: Kefkius/scallop
    def test_coinstake(self):
        tx = Transaction(self.coinstake_tx)
        tx.deserialize()

        self.assertEquals(tx.is_coinstake, True)
コード例 #34
0
 def test_peercoin_serialize(self):
     chainparams.set_active_chain('PPC')
     rawtx = '0100000058e4615501a367e883a383167e64c84e9c068ba5c091672e434784982f877eede589cb7e53000000006a473044022043b9aee9187effd7e6c7bc444b09162570f17e36b4a9c02cf722126cc0efa3d502200b3ba14c809fa9a6f7f835cbdbbb70f2f43f6b30beaf91eec6b8b5981c80cea50121025edf500f18f9f2b3f175f823fa996fbb2ec52982a9aeb1dc2e388a651054fb0fffffffff0257be0100000000001976a91495efca2c6a6f0e0f0ce9530219b48607a962e77788ac45702000000000001976a914f28abfb465126d6772dcb4403b9e1ad2ea28a03488ac00000000'
     tx = Transaction.deserialize(rawtx, chainparams.get_active_chain())
     self.assertEqual(tx.serialize()[8:16], rawtx[8:16])
コード例 #35
0
 def test_serialize(self):
     chainparams.set_active_chain('BTC')
     rawtx = '010000000198fb6f1c46eb0416b6a91bc9d0b8dfa554a96b23f00070f430bbf6d05b26ea16010000006c493046022100d00ff7bb2e9d41ef200ceb2fd874468b09a21e549ead6f2a74f35ad02ce25df8022100b1307da37c806ae638502c60d0ebbbe6da2ae9bb03f8798953059269e0ef3b46012102e7d08484e6c4c26bd2a3aabab09c65bbdcb4a6bba0ee5cf7008ef19b9540f818ffffffff0200743ba40b0000001976a91429a158767437cd82ccf4bd3e34ecd16c267fc36388aca0c01319180000001976a9140b31340661bb7a4165736ca2fc6509164b1dc96488ac00000000'
     tx = Transaction.deserialize(rawtx, chainparams.get_active_chain())
     self.assertEqual(str(tx), rawtx)
コード例 #36
0
ファイル: test_multisig.py プロジェクト: martexcoin/encompass
    def test_transaction(self):

        wallet_keys = {
            'xpub6GDQf5vZmrpQvD4ixNdqHmgSZ76Uo2Cg5isBupnvZpnNbhdRhgdhq9hkfCSKRE31rGfYuXNfZ5gTamFkj1GXt6k87MD1hUn28tuvLHY71Bk': 'L2FQCaHPwgS4CmAf6bKtbjVWDbcHv42c72by1zLEyLuDrUG22CwM',
            'xpub6GLs33TeHkrLSTJ2uxiMLnuqxCHG9iBFCwjTwyg4EvzyxUi78U1sXxxRPUQfLGNEZRT3yYKEwR39ZbUtofEgcmTLtJdSetnFiQPEwTZRW5y': 'L1aD1WSA3UGU56sAmjfYVj1rK3fnSzWKj2wTsDTN1DpgUgPVwQCa',
            'xpub6Fc64k9RTc79yD7xErF2yKSdUraGBhGWDt1FomUFVCFg52165LZvvoGL59hebJBGtauFqNL5zMeRgPGV29sfQp6XqoiiD9E53UDatBhFZuk': 'L25eCRYrDNVNrTZV1XZhmaZti3dVsZz3egm1R7LsPHRdpYuyLYKE'
#            'xpub6GiSmJrVQC5q2m5cRcZvUgnGUsfeEqi3eEfUTgacnA33G8PAQnJeeMzpNAGUA9JL3goUui7BY52rVPwhmxMALkmFh5ZuwJDKrPv8ERkG3CK': 'L3jUPoR7fUwB9mwfuqqF79mHDpj5rpygQhdWntJ9ShZ9nbyRab5h'
        }

        acc = self.wallet.accounts["0"]
        redeem_script = '53210278a1a7de63493a8c8e0e7f4ebb13fd2a8144db25bb3bc2e5f44127a851a389332102ee780aa224c9fe54caff984205077b7cca08ced3188a3f3c639d83deda6b9a592103124429ddbed55593d0abea0d0d3d283eca4546e40017b2945f4666c561b494ba210312872f0aa80fa1a9bc7df77fa5be310f5441f7bfec798fe19209b04954dec8da54ae'

        coins = [ {'address': '32SbQbBthcMzRSpCw1ifAXqWviJGH5HKUk',
            'value': 600000,
            'prevout_n': 0,
            'prevout_hash': '1111111111111111111111111111111111111111111111111111111111111111',
            'height': 100000,
            'coinbase': 'True'
            } ]

        txin = coins[0]

        x_pubkeys = map( lambda x:bip32_public_derivation(x, "", "/0/0/0"), self.wallet.master_public_keys.values() )
        pubkeys = map(lambda x: deserialize_xkey(x)[4].encode('hex'), x_pubkeys)

        s = ''.join( map(lambda x: int_to_hex(x, 2), (0, 0)))
        x_pubkeys = map( lambda x: 'ff' + DecodeBase58Check(x).encode('hex') + s, x_pubkeys)
        pubkeys, x_pubkeys = zip( *sorted(zip(pubkeys, x_pubkeys)))
        txin['pubkeys'] = list(pubkeys)
        txin['x_pubkeys'] = list(x_pubkeys)
        txin['signatures'] = [None] * len(pubkeys)
        txin['redeemScript'] = redeem_script
        txin['num_sig'] = acc.multisig_m

        outputs = [ ('address', '1PyXgL1qmZPuxcVi9CcguQb3v7WUvQZBud', 500000) ]
        inputs = []
        tx = Transaction(inputs, outputs)
        tx.add_input(txin)
        self.wallet.sign_transaction(tx, "secret")

        #
        ins = tx.inputs_to_sign()
        keypairs = {}
        sec = None
        for innard in ins:
            # this is easier than the commented loop below
            in_xpub, _ = BIP32_Account.parse_xpubkey(innard)
            if wallet_keys.get(in_xpub):
                keypairs[ innard ] = wallet_keys[in_xpub]
            # ...
#            in_xpub, in_seq = BIP32_Account.parse_xpubkey(innard)
#            sec = None
#            for k, vaccount in self.wallet.accounts.items():
#                acc_v = vaccount.get_master_pubkeys()[0]
#                acc_xpub = bip32_public_derivation(acc_v, "", "/0/0")
#                if in_xpub == acc_xpub:
#                    pk = vaccount.get_private_key(in_seq, self.wallet, "secret")
#                    sec = pk[0]

#            if sec:
#                keypairs [ innard ] = sec

        if keypairs:
            tx.sign(keypairs)
        self.assertEqual('0100000001111111111111111111111111111111111111111111111111111111111111111100000000fd6701004730440220774e80fda89895d8bf3ac39c38f39456d31c1e857dc1c77c000f4de6c3de15fe02207b6d13b5ba17eadeb607f3ca56f693a0b777dae668584cefec0910a8bc90869a0147304402205e80562254972f873b5b59b1cdc81e422c7a2959d8868e5a54238fbfdf6f107002200204eef593812453ae2c22334c409f9ef25523cf9619399eb2d3c249673443dc01483045022100a81e69796aa5e5ae0d8924047e3c81a8dd64dfbc791caba6728ac7820aa114da022060b85875fd58223b7c61ef45fac2567a9f76934f947e4d03d927f5b078e1fb45014c8b53210278a1a7de63493a8c8e0e7f4ebb13fd2a8144db25bb3bc2e5f44127a851a389332102ee780aa224c9fe54caff984205077b7cca08ced3188a3f3c639d83deda6b9a592103124429ddbed55593d0abea0d0d3d283eca4546e40017b2945f4666c561b494ba210312872f0aa80fa1a9bc7df77fa5be310f5441f7bfec798fe19209b04954dec8da54aeffffffff0120a10700000000001976a914fc03ab7c28d17349f084f7cadde4dafc356918d388ac00000000', str(tx))

        ###########
        #
        serialized_tx = str(tx)
        tx2 = Transaction.deserialize(serialized_tx, active_chain = self.wallet.active_chain)
        self.assertEquals(4, len(  tx2.inputs[0]['x_pubkeys'])  )
        self.assertEquals(3, tx2.inputs[0]['num_sig']  )