def test_sending_between_p2sh_1of2_and_p2wpkh_p2sh(self, mock_write): wallet1a = WalletIntegrityHelper.create_multisig_wallet( [ keystore.from_seed('phone guilt ancient scan defy gasp off rotate approve ill word exchange', '', True), keystore.from_xpub('tpubD6NzVbkrYhZ4YPZ3ntVjqSCxiUUv2jikrUBU73Q3iJ7Y8iR41oYf991L5fanv7ciHjbjokdK2bjYqg1BzEUDxucU9qM5WRdBiY738wmgLP4') ], '1of2', gap_limit=2 ) # ^ second seed: kingdom now gift initial age right velvet exotic harbor enforce kingdom kick wallet2 = WalletIntegrityHelper.create_standard_wallet( # bip39: uniform tank success logic lesson awesome stove elegant regular desert drip device, der: m/49'/1'/0' keystore.from_xprv('uprv91HGbrNZTK4x8u22nbdYGzEuWPxjaHMREUi7CNhY64KsG5ZGnVM99uCa16EMSfrnaPTFxjbRdBZ2WiBkokoM8anzAy3Vpc52o88WPkitnxi'), gap_limit=2 ) # bootstrap wallet1 funding_tx = Transaction('010000000001027e20990282eb29588375ad04936e1e991af3bc5b9c6f1ab62eca8c25becaef6a01000000171600140e6a17fadc8bafba830f3467a889f6b211d69a00fdffffff51847fd6bcbdfd1d1ea2c2d95c2d8de1e34c5f2bd9493e88a96a4e229f564e800100000017160014ecdf9fa06856f9643b1a73144bc76c24c67774a6fdffffff021e8501000000000017a91451991bfa68fbcb1e28aa0b1e060b7d24003352e38700093d000000000017a914b0b9f31bace76cdfae2c14abc03e223403d7dc4b870247304402205e19721b92c6afd70cd932acb50815a36ee32ab46a934147d62f02c13aeacf4702207289c4a4131ef86e27058ff70b6cb6bf0e8e81c6cbab6dddd7b0a9bc732960e4012103fe504411c21f7663caa0bbf28931f03fae7e0def7bc54851e0194dfb1e2c85ef02483045022100e969b65096fba4f8b24eb5bc622d2282076241621f3efe922cc2067f7a8a6be702203ec4047dd2a71b9c83eb6a0875a6d66b4d65864637576c06ed029d3d1a8654b0012102bbc8100dca67ba0297aba51296a4184d714204a5fc2eda34708360f37019a3dccfcc1300') funding_txid = funding_tx.txid() funding_output_value = 4000000 self.assertEqual('1137c12de4ce0f5b08de8846ba14c0814351a7f0f31457c8ea51a5d4b3c891a3', funding_txid) wallet1a.receive_tx_callback(funding_txid, funding_tx, TX_HEIGHT_UNCONFIRMED) # wallet1 -> wallet2 outputs = [(bitcoin.TYPE_ADDRESS, wallet2.get_receiving_address(), 1000000)] tx = wallet1a.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(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('1b7e94860b9681d4e371928d40fdbd4641e991aa74f1a211f239c887047e4a2a', 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(), 300000)] tx = wallet2.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(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('f65edb0843ff44436dc5964fb6b298e157502b9b4a83dac6b82dd2d2a3247d0a', 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 - 1000000 - 5000 + 300000, 0), wallet1a.get_balance()) self.assertEqual((0, 1000000 - 5000 - 300000, 0), wallet2.get_balance())
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())
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
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')
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')
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()
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'])
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
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()
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
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"
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()
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))
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))
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()
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)})
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
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()
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)
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'}
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)
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], } )
def test_has_debit_shown(self): with freeze_time("2020-01-01"): transaction = Transaction(debit=10000) result = "01/01/2020 || || 100.00 || " assert transaction.display() == result
def test_has_balance_shown(self): with freeze_time("2020-01-01"): transaction = Transaction(balance=10000) result = "01/01/2020 || || || 100.00 " assert transaction.display() == result
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())
def test_inputs(self): try: with open(txintests_local) as f: testlist = json.load(f) print("Got script tests from %s; will not download." % (txintests_local, )) except IOError: print("Couldn't get script tests from %s; downloading from %s..." % (txintests_local, txintests_url)) testlist = requests.get(txintests_url).json() print("Starting %d tests on SLP's input validation" % len(testlist)) for test in testlist: description = test['description'] given_validity = {} #should_validity = {} txes = {} for d in test['when']: tx = Transaction(d['tx']) txid = tx.txid() txes[txid] = tx if d['valid'] is True: given_validity[txid] = 1 elif d['valid'] is False: given_validity[txid] = 2 else: raise ValueError(d['valid']) for d in test['should']: tx = Transaction(d['tx']) txid = tx.txid() txes[txid] = tx d['txid'] = txid #if d['valid'] is True: #should_validity[txid] = 1 #elif d['valid'] is False: #should_validity[txid] = 2 #else: #raise ValueError(d['valid']) for i, d in enumerate(test['should']): txid = d['txid'] with self.subTest(description=description, i=i): try: graph, jobmgr = slp_validator_0x01.setup_job( txes[txid], reset=True) except slp.SlpInvalidOutputMessage: # If output 0 is not OP_RETURN self.assertEqual(d['valid'], False) continue def fetch_hook(txids): l = [] for txid in txids: try: l.append(txes[txid]) except KeyError: pass ### Call proxy here! return l job = slp_validator_0x01.ValidationJob( graph, [txid], None, fetch_hook=fetch_hook, validitycache=given_validity) #if txid == '8a08b78ae434de0b1a26e56ae7e78bb11b20f8240eb3d97371fd46a609df7fc3': #graph.debugging = True #job.debugging_graph_state = True q = Queue() job.add_callback(q.put) jobmgr.add_job(job) try: q.get(timeout=3) # unlimited timeout except Empty: raise RuntimeError( "Timeout during validation unit test") n = next(iter(job.nodes.values())) if d['valid'] is True: self.assertEqual(n.validity, 1) elif d['valid'] is False: self.assertIn(n.validity, (2, 3)) else: raise ValueError(d['valid'])
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'])
def handle_get_user_feed(self, request): with Transaction() as tr: posts = Post.get_user_feed(tr.cursor, self.context['user_id']) return construct_result(200, construct_posts_list_response(posts))
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())
def test_has_date_formatted(self): with freeze_time("2020-01-01"): transaction = Transaction() result = "01/01/2020 || || || " assert transaction.display() == result