Example #1
0
 def _create_oracle_request(self,
                            input_chain_paths,
                            output_chain_paths,
                            spend_id,
                            tx,
                            verifications=None,
                            callback=None):
     """:nodoc:"""
     tx = deepcopy(
         tx
     )  # keep original Tx object intact, so that it is not mutated by fix_input_scripts below.
     # Have the Oracle sign the tx
     chain_paths = []
     input_scripts = []
     input_txs = []
     for i, inp in enumerate(tx.txs_in):
         input_tx = self.tx_db.get(inp.previous_hash)
         if input_tx is None:
             raise Error("could not look up tx for %s" %
                         (b2h(inp.previous_hash)))
         input_txs.append(input_tx)
         if input_chain_paths[i] is not None:
             redeem_script = self._account.script_for_path(
                 input_chain_paths[i]).script()
             input_scripts.append(redeem_script)
             chain_paths.append(input_chain_paths[i])
             fix_input_script(inp, redeem_script)
         else:
             input_scripts.append(None)
             chain_paths.append(None)
     req = {
         "walletAgent": self._wallet_agent,
         "transaction": {
             "bytes":
             b2h(stream_to_bytes(tx.stream)),
             "inputScripts": [(b2h(script) if script else None)
                              for script in input_scripts],
             "inputTransactions":
             [b2h(stream_to_bytes(tx.stream)) for tx in input_txs],
             "chainPaths":
             chain_paths,
             "outputChainPaths":
             output_chain_paths,
             "masterKeys":
             self._account.public_keys[0:-self.num_oracle_keys],
         }
     }
     if spend_id:
         req['spendId'] = spend_id
     if callback:
         req['callback'] = callback
     if verifications:
         req['verifications'] = verifications
     return req
Example #2
0
def dump_block(block, network):
    blob = stream_to_bytes(block.stream)
    print("%d bytes   block hash %s" % (len(blob), block.id()))
    print("version %d" % block.version)
    print("prior block hash %s" % b2h_rev(block.previous_block_hash))
    print("merkle root %s" % binascii.hexlify(block.merkle_root).decode("utf8"))
    print("timestamp %s" % datetime.datetime.utcfromtimestamp(block.timestamp).isoformat())
    print("difficulty %d" % block.difficulty)
    print("nonce %s" % block.nonce)
    print("%d transaction%s" % (len(block.txs), "s" if len(block.txs) != 1 else ""))
    for idx, tx in enumerate(block.txs):
        print("Tx #%d:" % idx)
        dump_tx(tx, netcode=network)
Example #3
0
def dump_header(tx):
    tx_bin = stream_to_bytes(tx.stream)
    print("Version: %2d  tx hash %s  %d bytes" % (tx.version, tx.id(), len(tx_bin)))
    print("TxIn count: %d; TxOut count: %d" % (len(tx.txs_in), len(tx.txs_out)))
    if tx.lock_time == 0:
        meaning = "valid anytime"
    elif tx.lock_time < LOCKTIME_THRESHOLD:
        meaning = "valid after block index %d" % tx.lock_time
    else:
        when = datetime.datetime.utcfromtimestamp(tx.lock_time)
        meaning = "valid on or after %s utc" % when.isoformat()
    print("Lock time: %d (%s)" % (tx.lock_time, meaning))
    print("Input%s:" % ('s' if len(tx.txs_in) != 1 else ''))
Example #4
0
def dump_block(block, network):
    blob = stream_to_bytes(block.stream)
    print("%d bytes   block hash %s" % (len(blob), block.id()))
    print("version %d" % block.version)
    print("prior block hash %s" % b2h_rev(block.previous_block_hash))
    print("merkle root %s" % b2h(block.merkle_root))
    print("timestamp %s" % datetime.datetime.utcfromtimestamp(block.timestamp).isoformat())
    print("difficulty %d" % block.difficulty)
    print("nonce %s" % block.nonce)
    print("%d transaction%s" % (len(block.txs), "s" if len(block.txs) != 1 else ""))
    for idx, tx in enumerate(block.txs):
        print("Tx #%d:" % idx)
        dump_tx(tx, network=network, verbose_signature=False, disassembly_level=0, do_trace=False, use_pdb=False)
 def _create_oracle_request(self, input_chain_paths, output_chain_paths, spend_id, tx, verifications=None, callback=None):
     """:nodoc:"""
     tx = deepcopy(tx)  # keep original Tx object intact, so that it is not mutated by fix_input_scripts below.
     # Have the Oracle sign the tx
     chain_paths = []
     input_scripts = []
     input_txs = []
     for i, inp in enumerate(tx.txs_in):
         input_tx = self.tx_db.get(inp.previous_hash)
         if input_tx is None:
             raise Error("could not look up tx for %s" % (b2h(inp.previous_hash)))
         input_txs.append(input_tx)
         if input_chain_paths[i] is not None:
             redeem_script = self._account.script_for_path(input_chain_paths[i]).script()
             input_scripts.append(redeem_script)
             chain_paths.append(input_chain_paths[i])
             fix_input_script(inp, redeem_script)
         else:
             input_scripts.append(None)
             chain_paths.append(None)
     req = {
         "walletAgent": self._wallet_agent,
         "transaction": {
             "bytes": b2h(stream_to_bytes(tx.stream)),
             "inputScripts": [(b2h(script) if script else None) for script in input_scripts],
             "inputTransactions": [b2h(stream_to_bytes(tx.stream)) for tx in input_txs],
             "chainPaths": chain_paths,
             "outputChainPaths": output_chain_paths,
             "masterKeys": self._account.public_keys[0:-self.num_oracle_keys],
         }
     }
     if spend_id:
         req['spendId'] = spend_id
     if callback:
         req['callback'] = callback
     if verifications:
         req['verifications'] = verifications
     return req
Example #6
0
def dump_header(tx):
    tx_bin = stream_to_bytes(tx.stream)
    print("Version: %2d  tx hash %s  %d bytes" % (tx.version, tx.id(), len(tx_bin)))
    if tx.has_witness_data():
        print("      segwit tx hash %s" % tx.w_id())
    print("TxIn count: %d; TxOut count: %d" % (len(tx.txs_in), len(tx.txs_out)))
    if tx.lock_time == 0:
        meaning = "valid anytime"
    elif tx.lock_time < LOCKTIME_THRESHOLD:
        meaning = "valid after block index %d" % tx.lock_time
    else:
        when = datetime.datetime.utcfromtimestamp(tx.lock_time)
        meaning = "valid on or after %s utc" % when.isoformat()
    print("Lock time: %d (%s)" % (tx.lock_time, meaning))
    print("Input%s:" % ('s' if len(tx.txs_in) != 1 else ''))
Example #7
0
def dump_block(block, netcode=None):
    if netcode is None:
        netcode = get_current_netcode()
    blob = stream_to_bytes(block.stream)
    print("%d bytes   block hash %s" % (len(blob), block.id()))
    print("version %d" % block.version)
    print("prior block hash %s" % b2h_rev(block.previous_block_hash))
    print("merkle root %s" % b2h(block.merkle_root))
    print("timestamp %s" % datetime.datetime.utcfromtimestamp(block.timestamp).isoformat())
    print("difficulty %d" % block.difficulty)
    print("nonce %s" % block.nonce)
    print("%d transaction%s" % (len(block.txs), "s" if len(block.txs) != 1 else ""))
    for idx, tx in enumerate(block.txs):
        print("Tx #%d:" % idx)
        dump_tx(tx, netcode=netcode, verbose_signature=False, disassembly_level=0, do_trace=False, use_pdb=False)
Example #8
0
def dump_block(block, netcode=None):
    if netcode is None:
        netcode = get_current_netcode()
    blob = stream_to_bytes(block.stream)
    print("%d bytes   block hash %s" % (len(blob), block.id()))
    print("version %d" % block.version)
    print("prior block hash %s" % b2h_rev(block.previous_block_hash))
    print("merkle root %s" % b2h(block.merkle_root))
    print("timestamp %s" % datetime.datetime.utcfromtimestamp(block.timestamp).isoformat())
    print("difficulty %d" % block.difficulty)
    print("nonce %s" % block.nonce)
    print("%d transaction%s" % (len(block.txs), "s" if len(block.txs) != 1 else ""))
    for idx, tx in enumerate(block.txs):
        print("Tx #%d:" % idx)
        dump_tx(tx, netcode=netcode)
Example #9
0
def dump_tx(tx, netcode='BTC'):
    address_prefix = address_prefix_for_netcode(netcode)
    tx_bin = stream_to_bytes(tx.stream)
    print("Version: %2d  tx hash %s  %d bytes   " %
          (tx.version, tx.id(), len(tx_bin)))
    print("TxIn count: %d; TxOut count: %d" %
          (len(tx.txs_in), len(tx.txs_out)))
    if tx.lock_time == 0:
        meaning = "valid anytime"
    elif tx.lock_time < LOCKTIME_THRESHOLD:
        meaning = "valid after block index %d" % tx.lock_time
    else:
        when = datetime.datetime.utcfromtimestamp(tx.lock_time)
        meaning = "valid on or after %s utc" % when.isoformat()
    print("Lock time: %d (%s)" % (tx.lock_time, meaning))
    print("Input%s:" % ('s' if len(tx.txs_in) != 1 else ''))
    missing_unspents = tx.missing_unspents()
    for idx, tx_in in enumerate(tx.txs_in):
        if tx.is_coinbase():
            print("%4d: COINBASE  %12.5f mBTC" %
                  (idx, satoshi_to_mbtc(tx.total_in())))
        else:
            suffix = ""
            if tx.missing_unspent(idx):
                address = tx_in.bitcoin_address(address_prefix=address_prefix)
            else:
                tx_out = tx.unspents[idx]
                sig_result = " sig ok" if tx.is_signature_ok(
                    idx) else " BAD SIG"
                suffix = " %12.5f mBTC %s" % (satoshi_to_mbtc(
                    tx_out.coin_value), sig_result)
                address = tx_out.bitcoin_address(netcode=netcode)
            t = "%4d: %34s from %s:%-4d%s" % (idx, address,
                                              b2h_rev(tx_in.previous_hash),
                                              tx_in.previous_index, suffix)
            print(t.rstrip())
    print("Output%s:" % ('s' if len(tx.txs_out) != 1 else ''))
    for idx, tx_out in enumerate(tx.txs_out):
        amount_mbtc = satoshi_to_mbtc(tx_out.coin_value)
        address = tx_out.bitcoin_address(netcode=netcode) or "(unknown)"
        print("%4d: %34s receives %12.5f mBTC" % (idx, address, amount_mbtc))
    if not missing_unspents:
        print("Total input  %12.5f mBTC" % satoshi_to_mbtc(tx.total_in()))
    print("Total output %12.5f mBTC" % satoshi_to_mbtc(tx.total_out()))
    if not missing_unspents:
        print("Total fees   %12.5f mBTC" % satoshi_to_mbtc(tx.fee()))
Example #10
0
def dump_tx(tx, netcode='BTC'):
    address_prefix = address_prefix_for_netcode(netcode)
    tx_bin = stream_to_bytes(tx.stream)
    print("Version: %2d  tx hash %s  %d bytes   " % (tx.version, tx.id(), len(tx_bin)))
    print("TxIn count: %d; TxOut count: %d" % (len(tx.txs_in), len(tx.txs_out)))
    if tx.lock_time == 0:
        meaning = "valid anytime"
    elif tx.lock_time < LOCKTIME_THRESHOLD:
        meaning = "valid after block index %d" % tx.lock_time
    else:
        when = datetime.datetime.utcfromtimestamp(tx.lock_time)
        meaning = "valid on or after %s utc" % when.isoformat()
    print("Lock time: %d (%s)" % (tx.lock_time, meaning))
    print("Input%s:" % ('s' if len(tx.txs_in) != 1 else ''))
    missing_unspents = tx.missing_unspents()
    for idx, tx_in in enumerate(tx.txs_in):
        if tx.is_coinbase():
            print("%3d: COINBASE  %12.5f mBTC" % (idx, satoshi_to_mbtc(tx.total_in())))
        else:
            suffix = ""
            if tx.missing_unspent(idx):
                address = tx_in.bitcoin_address(address_prefix=address_prefix)
            else:
                tx_out = tx.unspents[idx]
                sig_result = " sig ok" if tx.is_signature_ok(idx) else " BAD SIG"
                suffix = " %12.5f mBTC %s" % (satoshi_to_mbtc(tx_out.coin_value), sig_result)
                address = tx_out.bitcoin_address(netcode=netcode)
            print("%3d: %34s from %s:%d%s" % (idx, address, b2h_rev(tx_in.previous_hash),
                  tx_in.previous_index, suffix))
    print("Output%s:" % ('s' if len(tx.txs_out) != 1 else ''))
    for idx, tx_out in enumerate(tx.txs_out):
        amount_mbtc = satoshi_to_mbtc(tx_out.coin_value)
        address = tx_out.bitcoin_address(netcode=netcode) or "(unknown)"
        print("%3d: %34s receives %12.5f mBTC" % (idx, address, amount_mbtc))
    if not missing_unspents:
        print("Total input  %12.5f mBTC" % satoshi_to_mbtc(tx.total_in()))
    print(    "Total output %12.5f mBTC" % satoshi_to_mbtc(tx.total_out()))
    if not missing_unspents:
        print("Total fees   %12.5f mBTC" % satoshi_to_mbtc(tx.fee()))
Example #11
0
def dump_tx(tx, netcode, verbose_signature, disassembly_level, do_trace):
    address_prefix = address_prefix_for_netcode(netcode)
    tx_bin = stream_to_bytes(tx.stream)
    print("Version: %2d  tx hash %s  %d bytes   " % (tx.version, tx.id(), len(tx_bin)))
    print("TxIn count: %d; TxOut count: %d" % (len(tx.txs_in), len(tx.txs_out)))
    if tx.lock_time == 0:
        meaning = "valid anytime"
    elif tx.lock_time < LOCKTIME_THRESHOLD:
        meaning = "valid after block index %d" % tx.lock_time
    else:
        when = datetime.datetime.utcfromtimestamp(tx.lock_time)
        meaning = "valid on or after %s utc" % when.isoformat()
    print("Lock time: %d (%s)" % (tx.lock_time, meaning))
    print("Input%s:" % ('s' if len(tx.txs_in) != 1 else ''))
    missing_unspents = tx.missing_unspents()
    traceback_f = trace_script if do_trace else None
    for idx, tx_in in enumerate(tx.txs_in):
        if disassembly_level > 0:
            signature_for_hash_type_f = lambda hash_type, script: tx.signature_hash(
                                        script, idx, hash_type)
        if tx.is_coinbase():
            print("%4d: COINBASE  %12.5f mBTC" % (idx, satoshi_to_mbtc(tx.total_in())))
        else:
            suffix = ""
            if tx.missing_unspent(idx):
                tx_out = None
                address = tx_in.bitcoin_address(address_prefix=address_prefix)
            else:
                tx_out = tx.unspents[idx]
                sig_result = " sig ok" if tx.is_signature_ok(idx, traceback_f=traceback_f) else " BAD SIG"
                suffix = " %12.5f mBTC %s" % (satoshi_to_mbtc(tx_out.coin_value), sig_result)
                address = tx_out.bitcoin_address(netcode=netcode)
            t = "%4d: %34s from %s:%-4d%s" % (idx, address, b2h_rev(tx_in.previous_hash),
                                              tx_in.previous_index, suffix)
            print(t.rstrip())
            if disassembly_level > 0:
                out_script = b''
                if tx_out:
                    out_script = tx_out.script
                for (pre_annotations, pc, opcode, instruction, post_annotations) in \
                        disassemble_scripts(tx_in.script, out_script, signature_for_hash_type_f):
                    for l in pre_annotations:
                        print("           %s" % l)
                    print(    "    %4x: %02x  %s" % (pc, opcode, instruction))
                    for l in post_annotations:
                        print("           %s" % l)

            if verbose_signature:
                signatures = []
                for opcode in opcode_list(tx_in.script):
                    if not opcode.startswith("OP_"):
                        try:
                            signatures.append(parse_signature_blob(h2b(opcode)))
                        except UnexpectedDER:
                            pass
                if signatures:
                    sig_types_identical = (zip(*signatures)[1]).count(signatures[0][1]) == len(signatures)
                    i = 1 if len(signatures) > 1 else ''
                    for sig_pair, sig_type in signatures:
                        print("      r{0}: {1:#x}\n      s{0}: {2:#x}".format(i, *sig_pair))
                        if not sig_types_identical and tx_out:
                            print("      z{}: {:#x} {}".format(i, tx.signature_hash(tx_out.script, idx, sig_type),
                                                               sighash_type_to_string(sig_type)))
                        if i: i += 1
                    if sig_types_identical and tx_out:
                        print("      z:{} {:#x} {}".format(' ' if i else '', tx.signature_hash(tx_out.script, idx, sig_type),
                                                           sighash_type_to_string(sig_type)))

    print("Output%s:" % ('s' if len(tx.txs_out) != 1 else ''))
    for idx, tx_out in enumerate(tx.txs_out):
        amount_mbtc = satoshi_to_mbtc(tx_out.coin_value)
        address = tx_out.bitcoin_address(netcode=netcode) or "(unknown)"
        print("%4d: %34s receives %12.5f mBTC" % (idx, address, amount_mbtc))
        if disassembly_level > 0:
            for (pre_annotations, pc, opcode, instruction, post_annotations) in \
                    disassemble_scripts(b'', tx_out.script, signature_for_hash_type_f):
                for l in pre_annotations:
                    print("           %s" % l)
                print(    "    %4x: %02x  %s" % (pc, opcode, instruction))
                for l in post_annotations:
                    print("           %s" % l)

    if not missing_unspents:
        print("Total input  %12.5f mBTC" % satoshi_to_mbtc(tx.total_in()))
    print(    "Total output %12.5f mBTC" % satoshi_to_mbtc(tx.total_out()))
    if not missing_unspents:
        print("Total fees   %12.5f mBTC" % satoshi_to_mbtc(tx.fee()))
Example #12
0
def dump_tx(tx, netcode, verbose_signature, disassembly_level, do_trace,
            use_pdb):
    address_prefix = address_prefix_for_netcode(netcode)
    tx_bin = stream_to_bytes(tx.stream)
    #     print("Tx_type:%2d" % tx.tx_type)
    if TransactionUtils.isCFTransation(tx):
        print("original_hash : %s" % tx.cf_header.original_hash)
        print("target_amount : %s" % tx.cf_header.target_amount)
        print("pubkey : %s" % tx.cf_header.pubkey)
        print("end_time : %s" % tx.cf_header.end_time)
        print("pre_hash : %s" % tx.cf_header.pre_hash)
        print("lack_amount : %s" % tx.cf_header.lack_amount)
    print("Version: %2d  tx hash %s  %d bytes   " %
          (tx.version, tx.id(), len(tx_bin)))
    print("TransactionIn count: %d; TransactionOut count: %d" %
          (len(tx.txs_in), len(tx.txs_out)))
    if tx.lock_time == 0:
        meaning = "valid anytime"
    elif tx.lock_time < LOCKTIME_THRESHOLD:
        meaning = "valid after block index %d" % tx.lock_time
    else:
        when = datetime.datetime.utcfromtimestamp(tx.lock_time)
        meaning = "valid on or after %s utc" % when.isoformat()
    print("Lock time: %d (%s)" % (tx.lock_time, meaning))
    print("Input%s:" % ('s' if len(tx.txs_in) != 1 else ''))
    missing_unspents = tx.missing_unspents()

    def trace_script(old_pc, opcode, data, stack, altstack, if_condition_stack,
                     is_signature):
        from pycoin.tx.script.tools import disassemble_for_opcode_data
        print("%3d : %02x  %s" %
              (old_pc, opcode, disassemble_for_opcode_data(opcode, data)))
        if use_pdb:
            import pdb
            from pycoin.serialize import b2h
            print("stack: [%s]" % ', '.join(b2h(s) for s in stack))
            if len(altstack) > 0:
                print("altstack: %s" % altstack)
            if len(if_condition_stack) > 0:
                print("condition stack: %s" %
                      ', '.join(int(s) for s in if_condition_stack))
            pdb.set_trace()

    traceback_f = trace_script if do_trace or use_pdb else None
    for idx, tx_in in enumerate(tx.txs_in):
        if disassembly_level > 0:

            def signature_for_hash_type_f(hash_type, script):
                return tx.signature_hash(script, idx, hash_type)

        if tx.is_coinbase():
            print("%4d: COINBASE  %12.5f mBTC" %
                  (idx, satoshi_to_mbtc(tx.total_in())))
        else:
            suffix = ""
            if tx.missing_unspent(idx):
                tx_out = None
                address = tx_in.bitcoin_address(address_prefix=address_prefix)
            else:
                tx_out = tx.unspents[idx]
                sig_result = " sig ok" if tx.is_signature_ok(
                    idx, traceback_f=traceback_f) else " BAD SIG"
                suffix = " %12.5f mBTC %s" % (satoshi_to_mbtc(
                    tx_out.coin_value), sig_result)
                address = tx_out.bitcoin_address(netcode=netcode)
            t = "%4d: %34s from %s:%-4d%s" % (idx, address,
                                              b2h_rev(tx_in.previous_hash),
                                              tx_in.previous_index, suffix)
            print(t.rstrip())
            if disassembly_level > 0:
                out_script = b''
                if tx_out:
                    out_script = tx_out.script
                for (pre_annotations, pc, opcode, instruction, post_annotations) in \
                        disassemble_scripts(
                            tx_in.script, out_script, tx.lock_time, signature_for_hash_type_f):
                    for l in pre_annotations:
                        print("           %s" % l)
                    print("    %4x: %02x  %s" % (pc, opcode, instruction))
                    for l in post_annotations:
                        print("           %s" % l)

            if verbose_signature:
                signatures = []
                for opcode in opcode_list(tx_in.script):
                    if not opcode.startswith("OP_"):
                        try:
                            signatures.append(parse_signature_blob(
                                h2b(opcode)))
                        except UnexpectedDER:
                            pass
                if signatures:
                    sig_types_identical = (zip(*signatures)[1]).count(
                        signatures[0][1]) == len(signatures)
                    i = 1 if len(signatures) > 1 else ''
                    for sig_pair, sig_type in signatures:
                        print("      r{0}: {1:#x}\n      s{0}: {2:#x}".format(
                            i, *sig_pair))
                        if not sig_types_identical and tx_out:
                            print("      z{}: {:#x} {}".format(
                                i,
                                tx.signature_hash(tx_out.script, idx,
                                                  sig_type),
                                sighash_type_to_string(sig_type)))
                        if i:
                            i += 1
                    if sig_types_identical and tx_out:
                        print("      z:{} {:#x} {}".format(
                            ' ' if i else '',
                            tx.signature_hash(tx_out.script, idx, sig_type),
                            sighash_type_to_string(sig_type)))

    print("Output%s:" % ('s' if len(tx.txs_out) != 1 else ''))
    for idx, tx_out in enumerate(tx.txs_out):
        amount_mbtc = satoshi_to_mbtc(tx_out.coin_value)
        address = tx_out.bitcoin_address(netcode=netcode) or "(unknown)"
        print("%4d: %34s receives %12.5f mBTC" % (idx, address, amount_mbtc))
        if disassembly_level > 0:
            for (pre_annotations, pc, opcode, instruction, post_annotations) in \
                    disassemble_scripts(b'', tx_out.script, tx.lock_time, signature_for_hash_type_f):
                for l in pre_annotations:
                    print("           %s" % l)
                print("    %4x: %02x  %s" % (pc, opcode, instruction))
                for l in post_annotations:
                    print("           %s" % l)

    if not missing_unspents:
        print("Total input  %12.5f mBTC" % satoshi_to_mbtc(tx.total_in()))
    print("Total output %12.5f mBTC" % satoshi_to_mbtc(tx.total_out()))
    if not missing_unspents:
        print("Total fees   %12.5f mBTC" % satoshi_to_mbtc(tx.fee()))
Example #13
0
def main():
    parser = argparse.ArgumentParser(
        description='DigitalOracle HD multisig command line utility',
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    parser.add_argument('-e', '--email', help='e-mail for create')
    parser.add_argument(
        '-p',
        '--phone',
        help='phone number for create - in the format +14155551212')
    parser.add_argument('-n',
                        '--network',
                        default='BTC',
                        choices=NETWORK_NAMES)
    parser.add_argument('-i',
                        "--inputpath",
                        nargs='+',
                        help='HD subkey path for each input (example: 0/2/15)')
    parser.add_argument(
        '-c',
        "--changepath",
        nargs='+',
        help=
        'HD subkey path for each change output (example: 0/2/15) or a dash for non-change outputs'
    )
    parser.add_argument(
        '-s',
        "--spendid",
        help=
        'an additional hex string to disambiguate spends to the same address')
    parser.add_argument(
        '-u',
        "--baseurl",
        help=
        'the API endpoint, defaults to the sandbox - https://s.digitaloracle.co/'
    )
    parser.add_argument('-v',
                        "--verbose",
                        default=0,
                        action="count",
                        help="Verbosity, use more -v flags for more verbosity")
    parser.add_argument('command', help="""a command""")
    parser.add_argument('item', nargs='+', help="""a key""")
    parser.epilog = textwrap.dedent("""
    Items:
     * P:wallet_passphrase - a secret for deriving an HD hierarchy with private keys
     * xpub - an account extended public key for deriving an HD hierarchy with public keys only
     * FILE.bin - unsigned transaction binary
     * FILE.hex - unsigned transaction hex

    Commands:
     * dump - dump the public subkeys
     * create - create Oracle account based on the supplied leading key with with any additional keys
     * address - get the deposit address for a subkey path
     * sign - sign a transaction, tx.bin or tx.hex must be supplied. Only one subkey path is supported.

    Notes:
     * --subkey is applicable for the address and sign actions, but not the create action
    """)
    args = parser.parse_args()

    keys = []
    txs = []
    for item in args.item:
        key = None
        tx = None
        if item.startswith('P:'):
            s = item[2:]
            key = BIP32Node.from_master_secret(s.encode('utf8'),
                                               netcode=args.network)
            keys.append(key)
        else:
            try:
                key = Key.from_text(item)
                keys.append(key)
            except encoding.EncodingError:
                pass
        if key is None:
            if os.path.exists(item):
                try:
                    with open(item, "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 as ex:
                    print('could not parse %s %s' % (item, ex),
                          file=sys.stderr)
                    pass
        if tx is None and key is None:
            print('could not understand item %s' % (item, ))

    account = MultisigAccount(keys, complete=False)
    oracle = Oracle(account, tx_db=get_tx_db(), base_url=args.baseurl)
    oracle.verbose = args.verbose

    if args.command == 'dump':
        sub_keys = [
            key.subkey_for_path(path or "")
            for key, path in izip_longest(keys, args.inputpath)
        ]
        for key in sub_keys:
            print(key.wallet_key(as_private=False))
    elif args.command == 'create':
        calls = []
        if args.email:
            calls.append('email')
        if args.phone:
            calls.append('phone')
        parameters = {
            "levels": [{
                "asset": "BTC",
                "period": 60,
                "value": 0.001
            }, {
                "delay": 0,
                "calls": calls
            }]
        }
        oracle.create(parameters, email=args.email, phone=args.phone)
    elif args.command == 'address':
        oracle.get()
        path = args.inputpath[0] if args.inputpath else ""
        payto = account.payto_for_path(path)
        if args.verbose > 0:
            sub_keys = [key.subkey_for_path(path) for key in account.keys]
            print("* account keys")
            print(account.keys)
            print("* child keys")
            for key in sub_keys:
                print(key.wallet_key(as_private=False))
            print("* address")
        print(payto.address(netcode=args.network))
    elif args.command == 'sign':
        oracle.get()
        scripts = [account.script_for_path(path) for path in args.inputpath]
        change_paths = [
            None if path == '-' else path for path in (args.changepath or [])
        ]
        for tx in txs:
            print(tx.id())
            print(b2h(stream_to_bytes(tx.stream)))
            sub_keys = [
                keys[0].subkey_for_path(path) for path in args.inputpath
            ]
            # sign locally
            local_sign(tx, scripts, sub_keys)
            # have Oracle sign
            result = oracle.sign_with_paths(tx,
                                            args.inputpath,
                                            change_paths,
                                            spend_id=args.spendid)
            print("Result:")
            print(result)
            if 'transaction' in result:
                print("Hex serialized transaction:")
                print(b2h(stream_to_bytes(result['transaction'].stream)))
    else:
        print('unknown command %s' % (args.command, ), file=sys.stderr)
Example #14
0
def main():
    parser = argparse.ArgumentParser(
        description="DigitalOracle HD multisig command line utility",
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    parser.add_argument("-e", "--email", help="e-mail for create")
    parser.add_argument("-p", "--phone", help="phone number for create - in the format +14155551212")
    parser.add_argument("-n", "--network", default="BTC", choices=NETWORK_NAMES)
    parser.add_argument("-i", "--inputpath", nargs="+", help="HD subkey path for each input (example: 0/2/15)")
    parser.add_argument(
        "-c",
        "--changepath",
        nargs="+",
        help="HD subkey path for each change output (example: 0/2/15) or a dash for non-change outputs",
    )
    parser.add_argument("-s", "--spendid", help="an additional hex string to disambiguate spends to the same address")
    parser.add_argument(
        "-u", "--baseurl", help="the API endpoint, defaults to the sandbox - https://s.digitaloracle.co/"
    )
    parser.add_argument(
        "-v", "--verbose", default=0, action="count", help="Verbosity, use more -v flags for more verbosity"
    )
    parser.add_argument("command", help="""a command""")
    parser.add_argument("item", nargs="+", help="""a key""")
    parser.epilog = textwrap.dedent(
        """
    Items:
     * P:wallet_passphrase - a secret for deriving an HD hierarchy with private keys
     * xpub - an account extended public key for deriving an HD hierarchy with public keys only
     * FILE.bin - unsigned transaction binary
     * FILE.hex - unsigned transaction hex

    Commands:
     * dump - dump the public subkeys
     * create - create Oracle account based on the supplied leading key with with any additional keys
     * address - get the deposit address for a subkey path
     * sign - sign a transaction, tx.bin or tx.hex must be supplied. Only one subkey path is supported.

    Notes:
     * --subkey is applicable for the address and sign actions, but not the create action
    """
    )
    args = parser.parse_args()

    keys = []
    txs = []
    for item in args.item:
        key = None
        tx = None
        if item.startswith("P:"):
            s = item[2:]
            key = BIP32Node.from_master_secret(s.encode("utf8"), netcode=args.network)
            keys.append(key)
        else:
            try:
                key = Key.from_text(item)
                keys.append(key)
            except encoding.EncodingError:
                pass
        if key is None:
            if os.path.exists(item):
                try:
                    with open(item, "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 as ex:
                    print("could not parse %s %s" % (item, ex), file=sys.stderr)
                    pass
        if tx is None and key is None:
            print("could not understand item %s" % (item,))

    account = MultisigAccount(keys, complete=False)
    oracle = Oracle(account, tx_db=get_tx_db(), base_url=args.baseurl)
    oracle.verbose = args.verbose

    if args.command == "dump":
        sub_keys = [key.subkey_for_path(path or "") for key, path in izip_longest(keys, args.inputpath)]
        for key in sub_keys:
            print(key.wallet_key(as_private=False))
    elif args.command == "create":
        calls = []
        if args.email:
            calls.append("email")
        if args.phone:
            calls.append("phone")
        parameters = {"levels": [{"asset": "BTC", "period": 60, "value": 0.001}, {"delay": 0, "calls": calls}]}
        oracle.create(parameters, email=args.email, phone=args.phone)
    elif args.command == "address":
        oracle.get()
        path = args.inputpath[0] if args.inputpath else ""
        payto = account.payto_for_path(path)
        if args.verbose > 0:
            sub_keys = [key.subkey_for_path(path) for key in account.keys]
            print("* account keys")
            print(account.keys)
            print("* child keys")
            for key in sub_keys:
                print(key.wallet_key(as_private=False))
            print("* address")
        print(payto.address(netcode=args.network))
    elif args.command == "sign":
        oracle.get()
        scripts = [account.script_for_path(path) for path in args.inputpath]
        change_paths = [None if path == "-" else path for path in (args.changepath or [])]
        for tx in txs:
            print(tx.id())
            print(b2h(stream_to_bytes(tx.stream)))
            sub_keys = [keys[0].subkey_for_path(path) for path in args.inputpath]
            # sign locally
            local_sign(tx, scripts, sub_keys)
            # have Oracle sign
            result = oracle.sign_with_paths(tx, args.inputpath, change_paths, spend_id=args.spendid)
            print("Result:")
            print(result)
            if "transaction" in result:
                print("Hex serialized transaction:")
                print(b2h(stream_to_bytes(result["transaction"].stream)))
    else:
        print("unknown command %s" % (args.command,), file=sys.stderr)