def broadcastTransaction(self, transaction): print(transaction) t = Tx.tx_from_hex(transaction) deserializer = serializers.TxSerializer() tx = deserializer.deserialize(BytesIO(bytearray.fromhex(transaction))) h = t.id() print('BROADCAST:', str(tx.calculate_hash())[2:-1], h) #try: # t = Tx.tx_from_hex (transaction) # print ('OMG',t.id ()) #except Exception as e: # print (e) if not h in self.db['mempool']: mp = self.db['mempool'] mp[h] = tx self.db['mempool'] = mp self.db.sync() self.mempooltimer = Timer(1.0, self.announceTransactions) self.mempooltimer.start() return h
def get_tx(self, tx_hash): url = "%s/rawtx/%s" % (self.base_url, b2h_rev(tx_hash)) result = json.loads(urlopen(url).read().decode("utf8")) tx = Tx.tx_from_hex(result["rawtx"]) if tx.hash() == tx_hash: return tx return None
def get_tx(self, tx_hash): URL = "%s/api/rawtx/%s" % (self.base_url, b2h_rev(tx_hash)) r = json.loads(urlopen(URL).read().decode("utf8")) tx = Tx.tx_from_hex(r['rawtx']) if tx.hash() == tx_hash: return tx return None
def broadcastTransaction (self, transaction): print (transaction) t = Tx.tx_from_hex (transaction) deserializer = serializers.TxSerializer () tx = deserializer.deserialize (BytesIO (bytearray.fromhex(transaction))) h = t.id () print ('BROADCAST:', str (tx.calculate_hash ())[2:-1], h) #try: # t = Tx.tx_from_hex (transaction) # print ('OMG',t.id ()) #except Exception as e: # print (e) if not h in self.db['mempool']: mp = self.db['mempool'] mp[h] = tx self.db['mempool'] = mp self.db.sync () self.mempooltimer = Timer (1.0, self.announceTransactions) self.mempooltimer.start () return h
def check_unprocessed(top_height): for tx_hash in unprocessed_txs.members(): txid = hash_to_hex(tx_hash).decode() tx = Tx.tx_from_hex(txs[tx_hash].decode()) tx_blockchain = get_tx(txid) logging.info('Checking %s' % txid) if tx_blockchain.block_height == -1: continue if top_height - tx_blockchain.block_height + 1 >= REQUIRED_CONFIRMATIONS: # off by one error - if tx in top block that is 1 conf unprocessed_txs.remove(tx_hash) for out in tx.txs_out: address = out.bitcoin_address() if address not in all_addresses: continue account = Account(addr_to_uid[address]) satoshis = out.coin_value satoshis = int(satoshis / (1 + account.tip.get())) # scale for tip account.total_coins.incr(satoshis) node_minutes_d = calc_node_minutes(satoshis, exchange_rate=exchange_rate.get()) account.total_minutes.incr(node_minutes_d) total_nodeminutes.incr(node_minutes_d) nodes_recently_updated.append(account.uid) account.add_msg('Detected payment via txid: %s' % (txid,)) account.add_msg('Increased total paid by %.8f to %.8f (considering tip of %d %%)' % (satoshis / COIN, account.total_coins.get() / COIN, account.tip.get() * 100)) account.add_msg('Increased node life by %d minutes; expiring around %s' % (node_minutes_d, account.get_expiry().isoformat()))
def main(): tx = Tx.tx_from_hex(sys.argv[1]) print('Input Scripts:') for inp in tx.txs_in: print(' - ' + disassemble(inp.script)) print('Output Scripts:') for out in tx.txs_out: print(' - ' + disassemble(out.script))
def sign_with_paths(self, tx, input_chain_paths, output_chain_paths, spend_id=None, verifications=None, callback=None): """ Have the Oracle sign the transaction :param tx: the transaction to be signed :type tx: Tx :param input_chain_paths: the derivation path for each input, or None if the input does not need to be signed :type input_chain_paths: list[str or None] :param output_chain_paths: the derivation path for each change output, or None if the output is not change :type output_chain_paths: list[str or None] :param spend_id: an additional hex ID to disambiguate sends to the same outputs :type spend_id: str :param verifications: an optional dictionary with authorization code for each verification type. Keys include "otp" and "code" (for SMS). :type verifications: dict of [str, str] :return: a dictionary with the transaction in 'transaction' if successful :rtype: dict """ req = self._create_oracle_request(input_chain_paths, output_chain_paths, spend_id, tx, verifications, callback=callback) body = json.dumps(req) url = self._url() + "/transactions" if self.verbose > 0: print(body) self._request_logger.before('post', url, self._default_headers, body) response = requests.post(url, body, headers=self._default_headers) self._request_logger.after('post', url, response) if response.status_code >= 500: raise OracleInternalError(response.content) result = response.json() if response.status_code == 200 and result.get('result', None) == 'success': tx = None if 'transaction' in result: tx = Tx.tx_from_hex(result['transaction']['bytes']) return SignatureResult({ 'transaction': tx, 'now': result['now'], 'spend_id': result['spendId'], 'deferral': result.get('deferral') }) if result.get('result') == 'deferred': deferral = result['deferral'] until = None if deferral and deferral['reason'] == 'delay': tzlocal = dateutil.tz.tzlocal() until = dateutil.parser.parse(deferral['until']).astimezone(tzlocal) #remain = int((until - datetime.datetime.now(tzlocal)).total_seconds()) raise OracleDeferralException(deferral.get('verifications'), until, result['spendId']) elif result.get('result') == 'rejected': raise OracleRejectionException() elif result.get('result') == 'locked': raise OracleLockoutException() elif result.get('error') == 'Platform velocity hard-limit exceeded': raise OraclePlatformVelocityHardLimitException('Platform velocity hard-limit exceeded') elif response.status_code == 200 or response.status_code == 400: raise OracleError(response.content) else: raise IOError("Unknown response %d" % (response.status_code,))
def post(self): logging.info("transaction coming in") hextx = self.get_argument('hextx', None) subkeys = self.get_argument('subkeys', None) payoutaddress = self.get_argument('payoutaddress', None) fees = self.get_argument('fees', None) print subkeys if not hextx or not subkeys or not payoutaddress or not fees: logging.error("Did not receive trans or tree argument") return fees = tornado.escape.json_decode(fees) subkeys = tornado.escape.json_decode(subkeys) seed = mnemonic.Mnemonic.to_seed(PHRASE) wallet = BIP32Node.from_master_secret(seed) wifs = [] keys = [] for subkey in subkeys: key = wallet.subkey_for_path(subkey) keys.append(key) wifs.append(key.wif()) underlying_script = ScriptMultisig( n=N, sec_keys=[key.sec() for key in keys[:M]]).script() address = address_for_pay_to_script(underlying_script) tx2 = Tx.tx_from_hex(hextx) # first tx out, need another for the 1% to our wallet script = standard_tx_out_script(payoutaddress) tx_out = TxOut(fees['seller'], script) # TODO: figure out final wallet. This is sending to my phone script = standard_tx_out_script("1LhkvTTxFXam672vjwbABtkp9td7dxCwyB") tx2_out = TxOut(fees['bestcrow'], script) txs_out = [tx_out, tx2_out] tx2.txs_out = txs_out hash160_lookup = build_hash160_lookup(key.secret_exponent() for key in keys) p2sh_lookup = build_p2sh_lookup([underlying_script]) tx2.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup) print tx2.as_hex() self.write(tx2.as_hex())
def broadcastTransaction (self, transaction): #print (transaction) t = Tx.tx_from_hex (transaction) h = t.id () #print ('BROADCAST:', t.id ()) if not h in self.db['mempool']: mp = self.db['mempool'] mp[h] = t self.db['mempool'] = mp self.db.sync () self.mempooltimer = Timer (1.0, self.announceTransactions) self.mempooltimer.start () return h
def broadcastTransaction(self, transaction): #print (transaction) t = Tx.tx_from_hex(transaction) h = t.id() #print ('BROADCAST:', t.id ()) if not h in self.db['mempool']: mp = self.db['mempool'] mp[h] = t self.db['mempool'] = mp self.db.sync() self.mempooltimer = Timer(1.0, self.announceTransactions) self.mempooltimer.start() return h
def got_message(self, message): if self.last_sent + 30 * 60 < time.time(): self.send_message(bitcoin.messages.msg_ping(self.ver_send)) self.print_debug("Received: %s" % repr(message)) if message.command == "version": self.send_message(bitcoin.messages.msg_verack(self.ver_send)) self.ver_send = min(self.ver_send, message.protover) elif message.command == "verack": self.ver_recv = self.ver_send elif message.command == "inv": self.request_objects(message.inv) elif message.command == "tx": self.new_tx_callback(Tx.tx_from_hex(message.tx.serialize().encode('hex'))) elif message.command == "block": self.new_block_callback(Block.parse(cStringIO.StringIO(message.block.serialize()))) # todo - use msg_block or block stream_serialize else: self.print_debug("received unknown message %s: %s" % (message.command, repr(message)))
def pycoin_sign_raw_transaction(tx_hex, private_key_wif): for char in private_key_wif: if char not in script.b58_digits: raise exceptions.TransactionError('invalid private key') if config.TESTNET: allowable_wif_prefixes = [config.PRIVATEKEY_VERSION_TESTNET] else: allowable_wif_prefixes = [config.PRIVATEKEY_VERSION_MAINNET] secret_exponent, compressed = wif_to_tuple_of_secret_exponent_compressed( private_key_wif, allowable_wif_prefixes=allowable_wif_prefixes) public_pair = public_pair_for_secret_exponent(generator_secp256k1, secret_exponent) hash160 = public_pair_to_hash160_sec(public_pair, compressed) hash160_lookup = {hash160: (secret_exponent, public_pair, compressed)} tx = Tx.tx_from_hex(tx_hex) for idx, tx_in in enumerate(tx.txs_in): tx.sign_tx_in(hash160_lookup, idx, tx_in.script, hash_type=SIGHASH_ALL) return tx.as_hex()
import mnemonic from pycoin.key.BIP32Node import BIP32Node from pycoin.tx.tx_utils import * from pycoin.tx import Tx # variables we'll receive from POST request tree = [u'0/0/122', u'0/0/123', u'0/0/124'] hex_tx = "010000000116a487e650ea0a55fa7a833b41ef63837da98efa717bbccd1c665c0d1e18f7a70100000000ffffffff01905f0100000000001976a9143f0bd6a98028466602aa347950811e714f7ee76988ac00000000" # generate wif's phrase = "sample core fitness wrong unusual inch hurry chaos myself credit welcome margin" seed = mnemonic.Mnemonic.to_seed(phrase) # XTN == testnet wallet = BIP32Node.from_master_secret(seed, 'XTN') wif = [] for subkey in tree: key = wallet.subkey_for_path(subkey) wif.append(key.wif()) # sign tx tx2 = Tx.tx_from_hex(hex_tx) signed = sign_tx(tx2, wif) print signed
def sign_with_paths(self, tx, input_chain_paths, output_chain_paths, spend_id=None, verifications=None, callback=None): """ Have the Oracle sign the transaction :param tx: the transaction to be signed :type tx: Tx :param input_chain_paths: the derivation path for each input, or None if the input does not need to be signed :type input_chain_paths: list[str or None] :param output_chain_paths: the derivation path for each change output, or None if the output is not change :type output_chain_paths: list[str or None] :param spend_id: an additional hex ID to disambiguate sends to the same outputs :type spend_id: str :param verifications: an optional dictionary with authorization code for each verification type. Keys include "otp" and "code" (for SMS). :type verifications: dict of [str, str] :return: a dictionary with the transaction in 'transaction' if successful :rtype: dict """ req = self._create_oracle_request(input_chain_paths, output_chain_paths, spend_id, tx, verifications, callback=callback) body = json.dumps(req) url = self._url() + "/transactions" if self.verbose > 0: print(body) self._request_logger.before('post', url, self._default_headers, body) response = requests.post(url, body, headers=self._default_headers) self._request_logger.after('post', url, response, self._default_headers, body) if response.status_code >= 500: raise OracleInternalError(response.content) result = response.json() if response.status_code == 200 and result.get('result', None) == 'success': tx = None if 'transaction' in result: tx = Tx.tx_from_hex(result['transaction']['bytes']) return SignatureResult({ 'transaction': tx, 'now': result['now'], 'spend_id': result['spendId'], 'deferral': result.get('deferral') }) if result.get('result') == 'deferred': deferral = result['deferral'] until = None if deferral and deferral['reason'] == 'delay': tzlocal = dateutil.tz.tzlocal() until = dateutil.parser.parse( deferral['until']).astimezone(tzlocal) #remain = int((until - datetime.datetime.now(tzlocal)).total_seconds()) raise OracleDeferralException(deferral.get('verifications'), until, result['spendId']) elif result.get('result') == 'rejected': raise OracleRejectionException() elif result.get('result') == 'locked': raise OracleLockoutException() elif result.get('error') == 'Platform velocity hard-limit exceeded': raise OraclePlatformVelocityHardLimitException( 'Platform velocity hard-limit exceeded') elif response.status_code == 200 or response.status_code == 400: raise OracleError(response.content) else: raise IOError("Unknown response %d" % (response.status_code, ))
for s in spendables: print s txs_in.append(s.tx_in()) # make tx_out on web server script = standard_tx_out_script(address) tx_out = TxOut(100000, script) txs_out = [tx_out] tx1 = Tx(version=1, txs_in=txs_in, txs_out=txs_out) tx1.set_unspents(txs_out) txhex = tx1.as_hex(include_unspents=True) # send txhex to private key server tx2 = Tx.tx_from_hex(txhex) script = standard_tx_out_script("1F8P3QEErMhm3fw6o23brRNQVaSMrG1maE") tx_out = TxOut(50000, script) script = standard_tx_out_script("1Dv9YWfVYMK1FjBhrCBc1diajSZKBj78MB") tx2_out = TxOut(50000, script) txs_out = [tx_out, tx2_out] tx2.txs_out = txs_out hash160_lookup = build_hash160_lookup(key.secret_exponent() for key in keys[:M]) p2sh_lookup = build_p2sh_lookup([underlying_script]) tx2.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup) print tx2.as_hex()
logging.basicConfig(level=logging.INFO) if __name__ == '__main__': while True: latest_block = get_latest_block() best_block_hash = latest_block.hash top_height = latest_block.height if best_block_hash == last_block_checked.get(): time.sleep(10) # only do this at most once per block continue logging.info('Latest block: %s' % best_block_hash) for tx_hash in unprocessed_txs.members(): txid = hash_to_hex(tx_hash).decode() tx = Tx.tx_from_hex(txs[tx_hash].decode()) tx_blockchain = get_tx(txid) logging.info('Checking %s' % txid) if tx_blockchain.block_height == -1: continue if top_height - tx_blockchain.block_height + 1 >= REQUIRED_CONFIRMATIONS: # off by one error - if tx in top block that is 1 conf unprocessed_txs.remove(tx_hash) for out in tx.txs_out: address = out.bitcoin_address() if address not in all_addresses: continue account = Account(addr_to_uid[address]) satoshis = out.coin_value satoshis = int(satoshis / (1 + account.tip.get())) # scale for tip account.total_coins.incr(satoshis) node_minutes_d = calc_node_minutes(satoshis, exchange_rate=exchange_rate.get())
def main(): parser = argparse.ArgumentParser( description="Manipulate bitcoin (or alt coin) transactions.", epilog=EPILOG) parser.add_argument('-t', "--transaction-version", type=int, help='Transaction version, either 1 (default) or 3 (not yet supported).') parser.add_argument('-l', "--lock-time", type=parse_locktime, help='Lock time; either a block' 'index, or a date/time (example: "2014-01-01T15:00:00"') parser.add_argument('-n', "--network", default="BTC", help='Define network code (M=Bitcoin mainnet, T=Bitcoin testnet).') parser.add_argument('-a', "--augment", action='store_true', help='augment tx by adding any missing spendable metadata by fetching' ' inputs from cache and/or web services') parser.add_argument("-i", "--fetch-spendables", metavar="address", action="append", help='Add all unspent spendables for the given bitcoin address. This information' ' is fetched from web services.') parser.add_argument('-f', "--private-key-file", metavar="path-to-private-keys", action="append", help='file containing WIF or BIP0032 private keys. If file name ends with .gpg, ' '"gpg -d" will be invoked automatically. File is read one line at a time, and if ' 'the file contains only one WIF per line, it will also be scanned for a bitcoin ' 'address, and any addresses found will be assumed to be public keys for the given' ' private key.', type=argparse.FileType('r')) parser.add_argument('-g', "--gpg-argument", help='argument to pass to gpg (besides -d).', default='') parser.add_argument("--remove-tx-in", metavar="tx_in_index_to_delete", action="append", type=int, help='remove a tx_in') parser.add_argument("--remove-tx-out", metavar="tx_out_index_to_delete", action="append", type=int, help='remove a tx_out') parser.add_argument('-F', "--fee", help='fee, in satoshis, to pay on transaction, or ' '"standard" to auto-calculate. This is only useful if the "split pool" ' 'is used; otherwise, the fee is automatically set to the unclaimed funds.', default="standard", metavar="transaction-fee", type=parse_fee) parser.add_argument('-C', "--cache", help='force the resultant transaction into the transaction cache.' ' Mostly for testing.', action='store_true'), parser.add_argument('-u', "--show-unspents", action='store_true', help='show TxOut items for this transaction in Spendable form.') parser.add_argument('-b', "--bitcoind-url", help='URL to bitcoind instance to validate against (http://user:pass@host:port).') parser.add_argument('-o', "--output-file", metavar="path-to-output-file", type=argparse.FileType('wb'), help='file to write transaction to. This supresses most other output.') parser.add_argument("argument", nargs="+", help='generic argument: can be a hex transaction id ' '(exactly 64 characters) to be fetched from cache or a web service;' ' a transaction as a hex string; a path name to a transaction to be loaded;' ' a spendable 4-tuple of the form tx_id/tx_out_idx/script_hex/satoshi_count ' 'to be added to TxIn list; an address/satoshi_count to be added to the TxOut ' 'list; an address to be added to the TxOut list and placed in the "split' ' pool".') args = parser.parse_args() # defaults txs = [] spendables = [] payables = [] key_iters = [] TX_ID_RE = re.compile(r"^[0-9a-fA-F]{64}$") # there are a few warnings we might optionally print out, but only if # they are relevant. We don't want to print them out multiple times, so we # collect them here and print them at the end if they ever kick in. warning_tx_cache = None warning_get_tx = None warning_spendables = None if args.private_key_file: wif_re = re.compile(r"[1-9a-km-zA-LMNP-Z]{51,111}") # address_re = re.compile(r"[1-9a-kmnp-zA-KMNP-Z]{27-31}") for f in args.private_key_file: if f.name.endswith(".gpg"): gpg_args = ["gpg", "-d"] if args.gpg_argument: gpg_args.extend(args.gpg_argument.split()) gpg_args.append(f.name) popen = subprocess.Popen(gpg_args, stdout=subprocess.PIPE) f = popen.stdout for line in f.readlines(): # decode if isinstance(line, bytes): line = line.decode("utf8") # look for WIFs possible_keys = wif_re.findall(line) def make_key(x): try: return Key.from_text(x) except Exception: return None keys = [make_key(x) for x in possible_keys] for key in keys: if key: key_iters.append((k.wif() for k in key.subkeys(""))) # if len(keys) == 1 and key.hierarchical_wallet() is None: # # we have exactly 1 WIF. Let's look for an address # potential_addresses = address_re.findall(line) # we create the tx_db lazily tx_db = None for arg in args.argument: # hex transaction id if TX_ID_RE.match(arg): if tx_db is None: warning_tx_cache = message_about_tx_cache_env() warning_get_tx = message_about_get_tx_env() tx_db = get_tx_db() tx = tx_db.get(h2b_rev(arg)) if not tx: for m in [warning_tx_cache, warning_get_tx, warning_spendables]: if m: print("warning: %s" % m, file=sys.stderr) parser.error("can't find Tx with id %s" % arg) txs.append(tx) continue # hex transaction data try: tx = Tx.tx_from_hex(arg) txs.append(tx) continue except Exception: pass try: key = Key.from_text(arg) # TODO: check network if key.wif() is None: payables.append((key.address(), 0)) continue # TODO: support paths to subkeys key_iters.append((k.wif() for k in key.subkeys(""))) continue except Exception: pass if os.path.exists(arg): try: with open(arg, "rb") as f: if f.name.endswith("hex"): f = io.BytesIO(codecs.getreader("hex_codec")(f).read()) tx = Tx.parse(f) txs.append(tx) try: tx.parse_unspents(f) except Exception as ex: pass continue except Exception: pass parts = arg.split("/") if len(parts) == 4: # spendable try: spendables.append(Spendable.from_text(arg)) continue except Exception: pass # TODO: fix allowable_prefixes allowable_prefixes = b'\0' if len(parts) == 2 and encoding.is_valid_bitcoin_address( parts[0], allowable_prefixes=allowable_prefixes): try: payables.append(parts) continue except ValueError: pass parser.error("can't parse %s" % arg) if args.fetch_spendables: warning_spendables = message_about_spendables_for_address_env() for address in args.fetch_spendables: spendables.extend(spendables_for_address(address)) for tx in txs: if tx.missing_unspents() and args.augment: if tx_db is None: warning_tx_cache = message_about_tx_cache_env() warning_get_tx = message_about_get_tx_env() tx_db = get_tx_db() tx.unspents_from_db(tx_db, ignore_missing=True) txs_in = [] txs_out = [] unspents = [] # we use a clever trick here to keep each tx_in corresponding with its tx_out for tx in txs: smaller = min(len(tx.txs_in), len(tx.txs_out)) txs_in.extend(tx.txs_in[:smaller]) txs_out.extend(tx.txs_out[:smaller]) unspents.extend(tx.unspents[:smaller]) for tx in txs: smaller = min(len(tx.txs_in), len(tx.txs_out)) txs_in.extend(tx.txs_in[smaller:]) txs_out.extend(tx.txs_out[smaller:]) unspents.extend(tx.unspents[smaller:]) for spendable in spendables: txs_in.append(spendable.tx_in()) unspents.append(spendable) for address, coin_value in payables: script = standard_tx_out_script(address) txs_out.append(TxOut(coin_value, script)) lock_time = args.lock_time version = args.transaction_version # if no lock_time is explicitly set, inherit from the first tx or use default if lock_time is None: if txs: lock_time = txs[0].lock_time else: lock_time = DEFAULT_LOCK_TIME # if no version is explicitly set, inherit from the first tx or use default if version is None: if txs: version = txs[0].version else: version = DEFAULT_VERSION if args.remove_tx_in: s = set(args.remove_tx_in) txs_in = [tx_in for idx, tx_in in enumerate(txs_in) if idx not in s] if args.remove_tx_out: s = set(args.remove_tx_out) txs_out = [tx_out for idx, tx_out in enumerate(txs_out) if idx not in s] tx = Tx(txs_in=txs_in, txs_out=txs_out, lock_time=lock_time, version=version, unspents=unspents) fee = args.fee try: distribute_from_split_pool(tx, fee) except ValueError as ex: print("warning: %s" % ex.args[0], file=sys.stderr) unsigned_before = tx.bad_signature_count() if unsigned_before > 0 and key_iters: def wif_iter(iters): while len(iters) > 0: for idx, iter in enumerate(iters): try: wif = next(iter) yield wif except StopIteration: iters = iters[:idx] + iters[idx+1:] break print("signing...", file=sys.stderr) sign_tx(tx, wif_iter(key_iters)) unsigned_after = tx.bad_signature_count() if unsigned_after > 0 and key_iters: print("warning: %d TxIn items still unsigned" % unsigned_after, file=sys.stderr) if len(tx.txs_in) == 0: print("warning: transaction has no inputs", file=sys.stderr) if len(tx.txs_out) == 0: print("warning: transaction has no outputs", file=sys.stderr) include_unspents = (unsigned_after > 0) tx_as_hex = tx.as_hex(include_unspents=include_unspents) if args.output_file: f = args.output_file if f.name.endswith(".hex"): f.write(tx_as_hex.encode("utf8")) else: tx.stream(f) if include_unspents: tx.stream_unspents(f) f.close() elif args.show_unspents: for spendable in tx.tx_outs_as_spendable(): print(spendable.as_text()) else: if not tx.missing_unspents(): check_fees(tx) dump_tx(tx, args.network) if include_unspents: print("including unspents in hex dump since transaction not fully signed") print(tx_as_hex) if args.cache: if tx_db is None: warning_tx_cache = message_about_tx_cache_env() warning_get_tx = message_about_get_tx_env() tx_db = get_tx_db() tx_db.put(tx) if args.bitcoind_url: if tx_db is None: warning_tx_cache = message_about_tx_cache_env() warning_get_tx = message_about_get_tx_env() tx_db = get_tx_db() validate_bitcoind(tx, tx_db, args.bitcoind_url) if tx.missing_unspents(): print("\n** can't validate transaction as source transactions missing", file=sys.stderr) else: try: if tx_db is None: warning_tx_cache = message_about_tx_cache_env() warning_get_tx = message_about_get_tx_env() tx_db = get_tx_db() tx.validate_unspents(tx_db) print('all incoming transaction values validated') except BadSpendableError as ex: print("\n**** ERROR: FEES INCORRECTLY STATED: %s" % ex.args[0], file=sys.stderr) except Exception as ex: print("\n*** can't validate source transactions as untampered: %s" % ex.args[0], file=sys.stderr) # print warnings for m in [warning_tx_cache, warning_get_tx, warning_spendables]: if m: print("warning: %s" % m, file=sys.stderr)
#!/usr/bin/env python3 import argparse import sys from pycoin.tx import Tx from models import txs, known_txs, unprocessed_txs, addr_to_uid, Account, known_blocks, all_addresses from wallet import process_tx_initial parser = argparse.ArgumentParser() parser.add_argument('--tx-hex') parser.add_argument('--txid') args = parser.parse_args() if args.txid in known_txs: sys.exit() tx = Tx.tx_from_hex(args.tx_hex) process_tx_initial(tx)