Exemple #1
0
def creatordispute(multi, identity, defaults, dry_run):
    """
    File a dispute (as a job creator).

    If you are a job creator, file a dispute on a job, for example if the job is
    not done on time.
    """
    (log, user, key, urls) = init(multi, identity)
    form = {}
    if defaults:
        form = parse_document(open(defaults).read())
        if 'Title' in form and form['Title'] != 'Rein Dispute Delivery':
            return click.echo("Input file type: " + form['Title'])
    store = False if dry_run else True

    Order.update_orders(rein, Document, Document.get_user_documents)

    documents = []
    orders = Order.get_user_orders(rein, Document)
    for order in orders:
        state = order.get_state(rein, Document)
        if state in ['offer', 'delivery']:
            # get parsed offer for this order and put it in an array
            documents += order.get_documents(rein, Document, state)

    contents = []
    for document in documents:
        contents.append(document.contents)

    valid_results = filter_and_parse_valid_sigs(rein, contents)

    not_our_orders = []
    for res in valid_results:
        if res['Job creator public key'] == key:
            not_our_orders.append(res)

    if len(not_our_orders) == 0:
        click.echo('None found')
        return

    if 'Job ID' in form.keys():
        doc = select_by_form(not_our_orders, 'Job ID', form)
    else:
        doc = dispute_prompt(rein, not_our_orders, "Deliverables")
    if not doc:
        return

    log.info('got delivery for dispute')
    fields = [
                {'label': 'Job name',                       'value_from': doc},
                {'label': 'Job ID',                         'value_from': doc},
                {'label': 'Dispute detail',                 'not_null': form},
                {'label': 'Primary escrow redeem script',   'value_from': doc},
                {'label': 'Mediator escrow redeem script',  'value_from': doc},
             ]
    document = assemble_document('Dispute Delivery', fields)
    res = sign_and_store_document(rein, 'creatordispute', document, user.daddr, user.dkey, store)
    if res and store:
        click.echo("Dispute signed by job creator. Run 'rein sync' to push to available servers.")
    log.info('creatordispute signed') if res else log.error('creatordispute failed')
Exemple #2
0
def status(multi, identity, jobid):
    """
    Show user info and active jobs.
    """
    (log, user, key, urls) = init(multi, identity)

    Order.update_orders(rein, Document, get_user_documents)
    documents = get_user_documents(rein)

    if jobid is None:
        click.echo("User: %s" % user.name)
        click.echo("Master bitcoin address: %s" % user.maddr)
        click.echo("Delegate bitcoin address: %s" % user.daddr)
        click.echo("Delegate public key: %s" % key)
        click.echo("Willing to mediate: %s" % user.will_mediate)
        if user.will_mediate: 
            click.echo("Mediator fee: %s %%" % user.mediator_fee)
        click.echo("Total document count: %s" % len(documents))   
        click.echo("Registered servers: ")
        for url in urls:
            click.echo("  " + url)
        click.echo("Testnet: %s" % PersistConfig.get_testnet(rein))
        click.echo('')
        click.echo('ID  Job ID                 Status')
        click.echo('-----------------------------------------------------')
        orders = Order.get_user_orders(rein, Document)
        for order in orders:
            past_tense = order.get_past_tense(order.get_state(rein, Document))
            click.echo("%s   %s   %s" % (order.id, order.job_id, past_tense))
    else:
        order = Order.get_by_job_id(rein, jobid)
        documents = order.get_documents(rein, Document)
        for document in documents:
            click.echo("\n" + document.contents)
Exemple #3
0
def status(multi, identity, jobid):
    """
    Show user info and active jobs.
    """
    (log, user, key, urls) = init(multi, identity)

    Order.update_orders(rein, Document, get_user_documents)
    documents = get_user_documents(rein)

    if jobid is None:
        click.echo("User: %s" % user.name)
        click.echo("Master bitcoin address: %s" % user.maddr)
        click.echo("Delegate bitcoin address: %s" % user.daddr)
        click.echo("Delegate public key: %s" % key)
        click.echo("Willing to mediate: %s" % user.will_mediate)
        if user.will_mediate:
            click.echo("Mediator fee: %s %%" % user.mediator_fee)
        click.echo("Total document count: %s" % len(documents))
        click.echo("Registered servers: ")
        for url in urls:
            click.echo("  " + url)
        click.echo("Testnet: %s" % PersistConfig.get_testnet(rein))
        click.echo('')
        click.echo('ID  Job ID                 Status')
        click.echo('-----------------------------------------------------')
        orders = Order.get_user_orders(rein, Document)
        for order in orders:
            past_tense = order.get_past_tense(order.get_state(rein, Document))
            click.echo("%s   %s   %s" % (order.id, order.job_id, past_tense))
    else:
        order = Order.get_by_job_id(rein, jobid)
        documents = order.get_documents(rein, Document)
        for document in documents:
            click.echo("\n" + document.contents)
Exemple #4
0
def workerdispute(multi, identity, defaults, dry_run):
    """
    File a dispute (as a worker).

    If you are a worker, file a dispute because the creator is
    unresponsive or does not accept work that fulfills the job
    specification, they would use this command to file a dispute.
    """
    (log, user, key, urls) = init(multi, identity)
    form = {}
    if defaults:
        form = parse_document(open(defaults).read())
        if 'Title' in form and form['Title'] != 'Rein Dispute Offer':
            return click.echo("Input file type: " + form['Title'])
    store = False if dry_run else True

    valid_results = []

    Order.update_orders(rein, Document, Document.get_user_documents)

    documents = []
    orders = Order.get_user_orders(rein, Document)
    for order in orders:
        state = order.get_state(rein, Document)
        if state in ['offer', 'delivery']:
            # get parsed offer for this order and put it in an array
            documents += order.get_documents(rein, Document, state)

    contents = []
    for document in documents:
        contents.append(document.contents)

    valid_results = filter_and_parse_valid_sigs(rein, contents)
    
    if len(valid_results) == 0:
        click.echo('None found')
        return

    if 'Job ID' in form.keys():
        doc = select_by_form(valid_results, 'Job ID', form)
    else:
        doc = dispute_prompt(rein, valid_results, 'Deliverables')
    if not doc:
        return

    log.info('got in-process job for dispute')
    fields = [
                {'label': 'Job name',                       'value_from': doc},
                {'label': 'Job ID',                         'value_from': doc},
                {'label': 'Dispute detail',                 'not_null': form},
                {'label': 'Primary escrow redeem script',   'value_from': doc},
                {'label': 'Mediator escrow redeem script',  'value_from': doc},
             ]
    document = assemble_document('Dispute Offer', fields)
    res = sign_and_store_document(rein, 'workerdispute', document, user.daddr, user.dkey, store)
    if res and store:
        click.echo("Dispute signed by worker. Run 'rein sync' to push to available servers.")
    log.info('workerdispute signed') if res else log.error('workerdispute failed')
Exemple #5
0
def workerdispute(multi, identity, defaults, dry_run):
    """
    File a dispute (as a worker).

    If you are a worker, file a dispute because the creator is
    unresponsive or does not accept work that fulfills the job
    specification, they would use this command to file a dispute.
    """
    (log, user, key, urls) = init(multi, identity)
    form = {}
    if defaults:
        form = parse_document(open(defaults).read())
        if 'Title' in form and form['Title'] != 'Rein Dispute Offer':
            return click.echo("Input file type: " + form['Title'])
    store = False if dry_run else True

    valid_results = []

    Order.update_orders(rein, Document, get_user_documents)

    documents = []
    orders = Order.get_user_orders(rein, Document)
    for order in orders:
        state = order.get_state(rein, Document)
        if state in ['offer', 'delivery']:
            # get parsed offer for this order and put it in an array
            documents += order.get_documents(rein, Document, state)

    contents = []
    for document in documents:
        contents.append(document.contents)

    valid_results = filter_and_parse_valid_sigs(rein, contents)
    
    if len(valid_results) == 0:
        click.echo('None found')
        return

    if 'Job ID' in form.keys():
        doc = select_by_form(valid_results, 'Job ID', form)
    else:
        doc = dispute_prompt(rein, valid_results, 'Deliverables')
    if not doc:
        return

    log.info('got in-process job for dispute')
    fields = [
                {'label': 'Job name',                       'value_from': doc},
                {'label': 'Job ID',                         'value_from': doc},
                {'label': 'Dispute detail',                 'not_null': form},
                {'label': 'Primary escrow redeem script',   'value_from': doc},
                {'label': 'Mediator escrow redeem script',  'value_from': doc},
             ]
    document = assemble_document('Dispute Offer', fields)
    res = sign_and_store_document(rein, 'workerdispute', document, user.daddr, user.dkey, store)
    if res and store:
        click.echo("Dispute signed by worker. Run 'rein sync' to push to available servers.")
    log.info('workerdispute signed') if res else log.error('workerdispute failed')
Exemple #6
0
def status(multi, identity, jobid):
    """
    Show user info and active jobs.
    """
    (log, user, key, urls) = init(multi, identity)

    Order.update_orders(rein, Document, Document.get_user_documents)
    documents = Document.get_user_documents(rein)

    if jobid is None:
        click.echo("User: %s" % user.name)
        click.echo("Master bitcoin address: %s" % user.maddr)
        click.echo("Delegate bitcoin address: %s" % user.daddr)
        click.echo("Delegate public key: %s" % key)
        click.echo("Willing to mediate: %s" % user.will_mediate)
        if user.will_mediate:
            click.echo("Mediator fee: %s %%" % user.mediator_fee)
        click.echo("Total document count: %s" % len(documents))
        click.echo("Registered servers: ")
        for url in urls:
            click.echo("  " + url)
        click.echo("Testnet: %s" % PersistConfig.get_testnet(rein))
        click.echo('')
        click.echo('ID  Job ID                 Status')
        click.echo('-----------------------------------------------------')
        orders = Order.get_user_orders(rein, Document)
        for order in orders:
            past_tense = order.get_past_tense(order.get_state(rein, Document))
            click.echo("%s   %s   %s" % (order.id, order.job_id, past_tense))
    else:
        remote_documents = []
        for url in urls:
            log.info("Querying %s for job id %s..." % (url, jobid))
            sel_url = "{0}query?owner={1}&query=by_job_id&job_ids={2}&testnet={3}"
            try:
                answer = requests.get(
                    url=sel_url.format(url, user.maddr, jobid, rein.testnet))
            except:
                click.echo('Error connecting to server.')
                log.error('server connect error ' + url)
                continue
            data = answer.json()
            remote_documents += filter_and_parse_valid_sigs(
                rein, data['by_job_id'])
        unique_documents = unique(remote_documents)
        for doc in remote_documents:
            click.echo(doc)
        if len(remote_documents) == 0:
            order = Order.get_by_job_id(rein, jobid)
            if order:
                documents = order.get_documents(rein, Document)
                for document in documents:
                    click.echo("\n" + document.contents)
            else:
                click.echo("Job id not found")
Exemple #7
0
def status(multi, identity, jobid):
    """
    Show user info and active jobs.
    """
    (log, user, key, urls) = init(multi, identity)

    Order.update_orders(rein, Document, Document.get_user_documents)
    documents = Document.get_user_documents(rein)

    if jobid is None:
        click.echo("User: %s" % user.name)
        click.echo("Master bitcoin address: %s" % user.maddr)
        click.echo("Delegate bitcoin address: %s" % user.daddr)
        click.echo("Delegate public key: %s" % key)
        click.echo("Willing to mediate: %s" % user.will_mediate)
        if user.will_mediate: 
            click.echo("Mediator fee: %s %%" % user.mediator_fee)
        click.echo("Total document count: %s" % len(documents))   
        click.echo("Registered servers: ")
        for url in urls:
            click.echo("  " + url)
        click.echo("Testnet: %s" % PersistConfig.get_testnet(rein))
        click.echo('')
        click.echo('ID  Job ID                 Status')
        click.echo('-----------------------------------------------------')
        orders = Order.get_user_orders(rein, Document)
        for order in orders:
            past_tense = order.get_past_tense(order.get_state(rein, Document))
            click.echo("%s   %s   %s" % (order.id, order.job_id, past_tense))
    else:
        remote_documents = []
        for url in urls:    
            log.info("Querying %s for job id %s..." % (url, jobid))
            sel_url = "{0}query?owner={1}&query=by_job_id&job_ids={2}&testnet={3}"
            try:
                answer = requests.get(url=sel_url.format(url, user.maddr, jobid, rein.testnet))
            except:
                click.echo('Error connecting to server.')
                log.error('server connect error ' + url)
                continue
            data = answer.json()
            remote_documents += filter_and_parse_valid_sigs(rein, data['by_job_id'])
        unique_documents = unique(remote_documents)
        for doc in remote_documents:
            click.echo(doc)
        if len(remote_documents) == 0:
            order = Order.get_by_job_id(rein, jobid)
            if order:
                documents = order.get_documents(rein, Document)
                for document in documents:
                    click.echo("\n" + document.contents)
            else:
                click.echo("Job id not found")
Exemple #8
0
def accept(multi, identity, defaults, dry_run):
    """
    Accept a delivery.

    Review and accept deliveries for your jobs. Once a delivery is
    accpted, mediators are advised not to sign any tranasctions
    refunding the job creator.
    """
    (log, user, key, urls) = init(multi, identity)
    form = {}
    if defaults:
        form = parse_document(open(defaults).read())
        if 'Title' in form and form['Title'] != 'Rein Accept Delivery':
            return click.echo("Input file type: " + form['Title'])
    store = False if dry_run else True

    Order.update_orders(rein, Document, Document.get_user_documents)

    documents = []
    orders = Order.get_user_orders(rein, Document)
    for order in orders:
        state = order.get_state(rein, Document)
        if state in ['offer', 'delivery']:
            # get parsed offer for this order and put it in an array
            documents += order.get_documents(rein, Document, state)

    contents = []
    for document in documents:
        contents.append(document.contents)

    valid_results = filter_and_parse_valid_sigs(rein, contents)

    our_orders = []
    for res in valid_results:
        if res['Job creator public key'] == key:
            order = Order.get_by_job_id(rein, res['Job ID'])
            res['state'] = order.get_state(rein, Document)
            our_orders.append(res)

    if len(our_orders) == 0:
        click.echo('None found')
        return

    if 'Job ID' in form.keys():
        doc = select_by_form(our_orders, 'Job ID', form)
    else:
        doc = accept_prompt(rein, our_orders, "Deliverables")
    if not doc:
        return

    log.info('got delivery for accept')

    fields = [
                {'label': 'Job name',                       'value_from': doc},
                {'label': 'Job ID',                         'value_from': doc},
                {'label': 'Signed primary payment',         'not_null': form},
                {'label': 'Signed mediator payment',        'not_null': form},
                {'label': 'Primary escrow redeem script',   'value_from': doc},
                {'label': 'Mediator escrow redeem script',  'value_from': doc},
             ]
    document = assemble_document('Accept Delivery', fields)
    click.echo('\n'+document+'\n')
    if click.confirm("Are you sure?"):
        res = sign_and_store_document(rein, 'accept', document, user.daddr, user.dkey, store)
        if res and store:
            click.echo("Accepted delivery. Run 'rein sync' to push to available servers.")
        log.info('accept signed') if res else log.error('accept failed')
    else:
        click.echo("Accept aborted.") 
Exemple #9
0
def deliver(multi, identity, defaults, dry_run):
    """
    Deliver on a job.

    Share deliverables with the creator of the job when completed. In the
    event of a dispute, mediators are advised to review the deliverables
    while deciding how to distribute funds.
    """
    (log, user, key, urls) = init(multi, identity)
    form = {}
    if defaults:
        form = parse_document(open(defaults).read())
        if 'Title' in form and form['Title'] != 'Rein Deliver':
            return click.echo("Input file type: " + form['Title'])
    store = False if dry_run else True

    Order.update_orders(rein, Document, Document.get_user_documents)

    documents = []
    orders = Order.get_user_orders(rein, Document)
    for order in orders:
        state = order.get_state(rein, Document)
        if state in ['offer', 'delivery']:
            # get parsed offer for this order and put it in an array
            documents += order.get_documents(rein, Document, state)

    contents = []
    for document in documents:
        contents.append(document.contents)

    offers = filter_and_parse_valid_sigs(rein, contents)

    not_our_orders = []
    for res in offers:
        if res['Job creator public key'] != key:
            not_our_orders.append(res)

    if len(not_our_orders) == 0:
        click.echo('None found')
        return

    if 'Job ID' in form.keys():
        doc = select_by_form(not_our_orders, 'Job ID', form)
    else:
        doc = delivery_prompt(rein, not_our_orders, 'Deliverables')
    if not doc:
        return

    log.info('got offer for delivery')
    fields = [
                {'label': 'Job name',                       'value_from': doc},
                {'label': 'Job ID',                         'value_from': doc},
                {'label': 'Deliverables',                   'not_null': form},
                {'label': 'Bid amount (BTC)',               'value_from': doc},
                {'label': 'Primary escrow address',         'value_from': doc},
                {'label': 'Mediator escrow address',        'value_from': doc},
                {'label': 'Primary escrow redeem script',   'value_from': doc},
                {'label': 'Mediator escrow redeem script',  'value_from': doc},
                {'label': 'Worker public key',              'value_from': doc},
                {'label': 'Mediator public key',            'value_from': doc},
                {'label': 'Job creator public key',         'value_from': doc},
             ]
    document = assemble_document('Delivery', fields)
    if check_redeem_scripts(document):
        res = sign_and_store_document(rein, 'delivery', document, user.daddr, user.dkey, store)
        if res and store:
            click.echo("Delivery created. Run 'rein sync' to push to available servers.")
    else:
        click.echo("Incorrect redeem scripts. Check keys and their order in redeem script.")
        res = False
    log.info('delivery signed') if res else log.error('delivery failed')
Exemple #10
0
def offer(multi, identity, defaults, dry_run):
    """
    Award a job.

    A job creator would use this command to award the job to a specific bid. 
    Once signed and pushed, escrow addresses should be funded and work can
    begin.
    """
    (log, user, key, urls) = init(multi, identity)
    form = {}
    if defaults:
        form = parse_document(open(defaults).read())
        if 'Title' in form and form['Title'] != 'Rein Offer':
            return click.echo("Input file type: " + form['Title'])
    store = False if dry_run else True

    bids = []
    for url in urls:
        log.info("Querying %s for bids on your jobs..." % url)
        sel_url = "{0}query?owner={1}&delegate={2}&query=bids&testnet={3}"
        try:
            answer = requests.get(url=sel_url.format(url, user.maddr, user.daddr, rein.testnet))
        except:
            click.echo('Error connecting to server.')
            log.error('server connect error ' + url)
            continue
        data = answer.json()
        bids += filter_and_parse_valid_sigs(rein, data['bids'])

    unique_bids = unique(bids, 'Description')

    bids = []
    for bid in unique_bids:
        order = Order.get_by_job_id(rein, bid['Job ID'])
        if not order:
            order = Order(bid['Job ID'], testnet=rein.testnet)
            rein.session.add(order)
            rein.session.commit()
        state = order.get_state(rein, Document)
        if state in ['bid', 'job_posting']:
            bids.append(bid)
    
    if len(bids) == 0:
        click.echo('None found')
        return

    if 'Worker public key' in form.keys():
        bid = select_by_form([bid], 'Worker public key', form)
    else:
        bid = bid_prompt(rein, bids)
    if not bid:
        return

    log.info('got bid to offer')
    fields = [
                {'label': 'Job name',                       'value_from': bid},
                {'label': 'Worker',                         'value_from': bid},
                {'label': 'Description',                    'value_from': bid},
                {'label': 'Bid amount (BTC)',               'value_from': bid},
                {'label': 'Primary escrow address',         'value_from': bid},
                {'label': 'Mediator escrow address',        'value_from': bid},
                {'label': 'Job ID',                         'value_from': bid},
                {'label': 'Job creator',                    'value_from': bid},
                {'label': 'Job creator public key',         'value_from': bid},
                {'label': 'Mediator public key',            'value_from': bid},
                {'label': 'Worker public key',              'value_from': bid},
                {'label': 'Primary escrow redeem script',   'value_from': bid},
                {'label': 'Mediator escrow redeem script',  'value_from': bid},
             ]
    document = assemble_document('Offer', fields)
    if not click.confirm('Are you sure you want to award this bid?'):
        return

    res = sign_and_store_document(rein, 'offer', document, user.daddr, user.dkey, store)
    if res and store:
        click.echo("Two funding addresses and corresponding redeem scripts have been created for\n"
                   "this job. When it is time to distribute payment, you would use the redeem\n"
                   "script and a tool like Rein's modified version of Coinb.in to build and sign\n"
                   "payment transactions. As long as there is no dispute, the job creator would\n"
                   "sign a transaction paying the worker all funds held by the primary escrow\n"
                   "address and the mediator all funds held by the mediator escrow address.\n")
        click.echo("Offer created. Run 'rein sync' to push to available servers.")
    log.info('offer signed') if res else log.error('offer failed')
Exemple #11
0
def bid(multi, identity, defaults, dry_run):
    """
    Bid on a job.

    Choose from available jobs posted to your registered servers your client knows
    about, and create a bid. Your bid should include the amount of Bitcoin you need
    to complete the job and when you expect to have it complete.
    """
    
    (log, user, key, urls) = init(multi, identity)
    form = {}
    if defaults:
        form = parse_document(open(defaults).read())
        if 'Title' in form and form['Title'] != 'Rein Bid':
            return click.echo("Input file type: " + form['Title'])
    store = False if dry_run else True

    jobs = []
    for url in urls:    
        log.info("Querying %s for jobs..." % url)
        sel_url = "{0}query?owner={1}&query=jobs&testnet={2}"
        try:
            answer = requests.get(url=sel_url.format(url, user.maddr, rein.testnet))
        except:
            click.echo('Error connecting to server.')
            log.error('server connect error ' + url)
            continue
        data = answer.json()
        jobs += filter_and_parse_valid_sigs(rein, data['jobs'])

    unique_jobs = unique(jobs, 'Job ID')

    jobs = []
    for job in unique_jobs:
        order = Order.get_by_job_id(rein, job['Job ID'])
        if not order:
            order = Order(job['Job ID'], testnet=rein.testnet)
            rein.session.add(order)
            rein.session.commit()
        state = order.get_state(rein, Document)
        if state in ['job_posting', 'bid']:
            jobs.append(job)
    
    if len(jobs) == 0:
        click.echo('None found')
        return

    if 'Job ID' in form.keys():
        job = select_by_form(jobs, 'Job ID', form)
    else:
        job = job_prompt(rein, jobs)
    if not job:
        return

    log.info('got job for bid')
    primary_redeem_script, primary_addr = build_2_of_3([job['Job creator public key'],
                                                        job['Mediator public key'],
                                                        key])
    mediator_redeem_script, mediator_escrow_addr = build_mandatory_multisig(job['Mediator public key'],
                                                                            [job['Job creator public key'],key])
    fields = [
                {'label': 'Job name',                       'value_from': job},
                {'label': 'Worker',                         'value': user.name},
                {'label': 'Worker contact',                 'value': user.contact},
                {'label': 'Description',                    'not_null': form},
                {'label': 'Bid amount (BTC)',               'not_null': form},
                {'label': 'Primary escrow address',         'value': primary_addr},
                {'label': 'Mediator escrow address',        'value': mediator_escrow_addr},
                {'label': 'Job ID',                         'value_from': job},
                {'label': 'Job creator',                    'value_from': job},
                {'label': 'Job creator public key',         'value_from': job},
                {'label': 'Mediator public key',            'value_from': job},
                {'label': 'Worker public key',              'value': key},
                {'label': 'Primary escrow redeem script',   'value': primary_redeem_script},
                {'label': 'Mediator escrow redeem script',  'value': mediator_redeem_script},
             ]
    document = assemble_document('Bid', fields)
    res = sign_and_store_document(rein, 'bid', document, user.daddr, user.dkey, store)
    if res and store:
        click.echo("Bid created. Run 'rein sync' to push to available servers.")
    log.info('bid signed') if res else log.error('bid failed')
Exemple #12
0
def accept(multi, identity, defaults, dry_run):
    """
    Accept a delivery.

    Review and accept deliveries for your jobs. Once a delivery is
    accpted, mediators are advised not to sign any tranasctions
    refunding the job creator.
    """
    (log, user, key, urls) = init(multi, identity)
    form = {}
    if defaults:
        form = parse_document(open(defaults).read())
        if 'Title' in form and form['Title'] != 'Rein Accept Delivery':
            return click.echo("Input file type: " + form['Title'])
    store = False if dry_run else True

    Order.update_orders(rein, Document, get_user_documents)

    documents = []
    orders = Order.get_user_orders(rein, Document)
    for order in orders:
        state = order.get_state(rein, Document)
        if state in ['offer', 'delivery']:
            # get parsed offer for this order and put it in an array
            documents += order.get_documents(rein, Document, state)

    contents = []
    for document in documents:
        contents.append(document.contents)

    valid_results = filter_and_parse_valid_sigs(rein, contents)

    our_orders = []
    for res in valid_results:
        if res['Job creator public key'] == key:
            our_orders.append(res)

    if len(our_orders) == 0:
        click.echo('None found')
        return

    if 'Job ID' in form.keys():
        doc = select_by_form(our_orders, 'Job ID', form)
    else:
        doc = accept_prompt(rein, our_orders, "Deliverables")
    if not doc:
        return

    log.info('got delivery for accept')

    fields = [
        {
            'label': 'Job name',
            'value_from': doc
        },
        {
            'label': 'Job ID',
            'value_from': doc
        },
        {
            'label': 'Signed primary payment',
            'not_null': form
        },
        {
            'label': 'Signed mediator payment',
            'not_null': form
        },
        {
            'label': 'Primary escrow redeem script',
            'value_from': doc
        },
        {
            'label': 'Mediator escrow redeem script',
            'value_from': doc
        },
    ]
    document = assemble_document('Accept Delivery', fields)
    click.echo('\n' + document + '\n')
    if click.confirm("Are you sure?"):
        res = sign_and_store_document(rein, 'accept', document, user.daddr,
                                      user.dkey, store)
        if res and store:
            click.echo(
                "Accepted delivery. Run 'rein sync' to push to available servers."
            )
        log.info('accept signed') if res else log.error('accept failed')
    else:
        click.echo("Accept aborted.")
Exemple #13
0
def deliver(multi, identity, defaults, dry_run):
    """
    Deliver on a job.

    Share deliverables with the creator of the job when completed. In the
    event of a dispute, mediators are advised to review the deliverables
    while deciding how to distribute funds.
    """
    (log, user, key, urls) = init(multi, identity)
    form = {}
    if defaults:
        form = parse_document(open(defaults).read())
        if 'Title' in form and form['Title'] != 'Rein Deliver':
            return click.echo("Input file type: " + form['Title'])
    store = False if dry_run else True

    Order.update_orders(rein, Document, get_user_documents)

    documents = []
    orders = Order.get_user_orders(rein, Document)
    for order in orders:
        state = order.get_state(rein, Document)
        if state in ['offer', 'delivery']:
            # get parsed offer for this order and put it in an array
            documents += order.get_documents(rein, Document, state)

    contents = []
    for document in documents:
        contents.append(document.contents)

    offers = filter_and_parse_valid_sigs(rein, contents)

    not_our_orders = []
    for res in offers:
        if res['Job creator public key'] != key:
            not_our_orders.append(res)

    if len(not_our_orders) == 0:
        click.echo('None found')
        return

    if 'Job ID' in form.keys():
        doc = select_by_form(not_our_orders, 'Job ID', form)
    else:
        doc = delivery_prompt(rein, not_our_orders, 'Deliverables')
    if not doc:
        return

    log.info('got offer for delivery')
    fields = [
        {
            'label': 'Job name',
            'value_from': doc
        },
        {
            'label': 'Job ID',
            'value_from': doc
        },
        {
            'label': 'Deliverables',
            'not_null': form
        },
        {
            'label': 'Bid amount (BTC)',
            'value_from': doc
        },
        {
            'label': 'Primary escrow address',
            'value_from': doc
        },
        {
            'label': 'Mediator escrow address',
            'value_from': doc
        },
        {
            'label': 'Primary escrow redeem script',
            'value_from': doc
        },
        {
            'label': 'Mediator escrow redeem script',
            'value_from': doc
        },
        {
            'label': 'Worker public key',
            'value_from': doc
        },
        {
            'label': 'Mediator public key',
            'value_from': doc
        },
        {
            'label': 'Job creator public key',
            'value_from': doc
        },
    ]
    document = assemble_document('Delivery', fields)
    if check_redeem_scripts(document):
        res = sign_and_store_document(rein, 'delivery', document, user.daddr,
                                      user.dkey, store)
        if res and store:
            click.echo(
                "Delivery created. Run 'rein sync' to push to available servers."
            )
    else:
        click.echo(
            "Incorrect redeem scripts. Check keys and their order in redeem script."
        )
        res = False
    log.info('delivery signed') if res else log.error('delivery failed')
Exemple #14
0
def offer(multi, identity, defaults, dry_run):
    """
    Award a job.

    A job creator would use this command to award the job to a specific bid. 
    Once signed and pushed, escrow addresses should be funded and work can
    begin.
    """
    (log, user, key, urls) = init(multi, identity)
    form = {}
    if defaults:
        form = parse_document(open(defaults).read())
        if 'Title' in form and form['Title'] != 'Rein Offer':
            return click.echo("Input file type: " + form['Title'])
    store = False if dry_run else True

    bids = []
    for url in urls:
        log.info("Querying %s for bids on your jobs..." % url)
        sel_url = "{0}query?owner={1}&delegate={2}&query=bids&testnet={3}"
        try:
            answer = requests.get(
                url=sel_url.format(url, user.maddr, user.daddr, rein.testnet))
        except:
            click.echo('Error connecting to server.')
            log.error('server connect error ' + url)
            continue
        data = answer.json()
        bids += filter_and_parse_valid_sigs(rein, data['bids'])

    unique_bids = unique(bids, 'Description')

    bids = []
    for bid in unique_bids:
        order = Order.get_by_job_id(rein, bid['Job ID'])
        if not order:
            order = Order(bid['Job ID'], testnet=rein.testnet)
            rein.session.add(order)
            rein.session.commit()
        state = order.get_state(rein, Document)
        if state in ['bid', 'job_posting']:
            bids.append(bid)

    if len(data['bids']) == 0:
        click.echo('None found')

    if 'Worker public key' in form.keys():
        bid = select_by_form([bid], 'Worker public key', form)
    else:
        bid = bid_prompt(rein, bids)
    if not bid:
        click.echo('None chosen')
        return

    log.info('got bid to offer')
    fields = [
        {
            'label': 'Job name',
            'value_from': bid
        },
        {
            'label': 'Worker',
            'value_from': bid
        },
        {
            'label': 'Description',
            'value_from': bid
        },
        {
            'label': 'Bid amount (BTC)',
            'value_from': bid
        },
        {
            'label': 'Primary escrow address',
            'value_from': bid
        },
        {
            'label': 'Mediator escrow address',
            'value_from': bid
        },
        {
            'label': 'Job ID',
            'value_from': bid
        },
        {
            'label': 'Job creator',
            'value_from': bid
        },
        {
            'label': 'Job creator public key',
            'value_from': bid
        },
        {
            'label': 'Mediator public key',
            'value_from': bid
        },
        {
            'label': 'Worker public key',
            'value_from': bid
        },
        {
            'label': 'Primary escrow redeem script',
            'value_from': bid
        },
        {
            'label': 'Mediator escrow redeem script',
            'value_from': bid
        },
    ]
    document = assemble_document('Offer', fields)
    if not click.confirm('Are you sure you want to award this bid?'):
        return

    res = sign_and_store_document(rein, 'offer', document, user.daddr,
                                  user.dkey, store)
    if res and store:
        click.echo(
            "Offer created. Run 'rein sync' to push to available servers.")
    log.info('offer signed') if res else log.error('offer failed')
Exemple #15
0
def bid(multi, identity, defaults, dry_run):
    """
    Bid on a job.

    Choose from available jobs posted to your registered servers your client knows
    about, and create a bid. Your bid should include the amount of Bitcoin you need
    to complete the job and when you expect to have it complete.
    """

    (log, user, key, urls) = init(multi, identity)
    form = {}
    if defaults:
        form = parse_document(open(defaults).read())
        if 'Title' in form and form['Title'] != 'Rein Bid':
            return click.echo("Input file type: " + form['Title'])
    store = False if dry_run else True

    jobs = []
    for url in urls:
        log.info("Querying %s for jobs..." % url)
        sel_url = "{0}query?owner={1}&query=jobs&testnet={2}"
        try:
            answer = requests.get(
                url=sel_url.format(url, user.maddr, rein.testnet))
        except:
            click.echo('Error connecting to server.')
            log.error('server connect error ' + url)
            continue
        data = answer.json()
        jobs += filter_and_parse_valid_sigs(rein, data['jobs'])

    unique_jobs = unique(jobs, 'Job ID')

    jobs = []
    for job in unique_jobs:
        order = Order.get_by_job_id(rein, job['Job ID'])
        if not order:
            order = Order(job['Job ID'], testnet=rein.testnet)
            rein.session.add(order)
            rein.session.commit()
        state = order.get_state(rein, Document)
        if state in ['job_posting', 'bid']:
            jobs.append(job)

    if len(jobs) == 0:
        click.echo('None found')
        return

    if 'Job ID' in form.keys():
        job = select_by_form(jobs, 'Job ID', form)
    else:
        job = job_prompt(rein, jobs)
    if not job:
        return

    log.info('got job for bid')
    primary_redeem_script, primary_addr = build_2_of_3(
        [job['Job creator public key'], job['Mediator public key'], key])
    mediator_redeem_script, mediator_escrow_addr = build_mandatory_multisig(
        job['Mediator public key'], [job['Job creator public key'], key])
    fields = [
        {
            'label': 'Job name',
            'value_from': job
        },
        {
            'label': 'Worker',
            'value': user.name
        },
        {
            'label': 'Description',
            'not_null': form
        },
        {
            'label': 'Bid amount (BTC)',
            'not_null': form
        },
        {
            'label': 'Primary escrow address',
            'value': primary_addr
        },
        {
            'label': 'Mediator escrow address',
            'value': mediator_escrow_addr
        },
        {
            'label': 'Job ID',
            'value_from': job
        },
        {
            'label': 'Job creator',
            'value_from': job
        },
        {
            'label': 'Job creator public key',
            'value_from': job
        },
        {
            'label': 'Mediator public key',
            'value_from': job
        },
        {
            'label': 'Worker public key',
            'value': key
        },
        {
            'label': 'Primary escrow redeem script',
            'value': primary_redeem_script
        },
        {
            'label': 'Mediator escrow redeem script',
            'value': mediator_redeem_script
        },
    ]
    document = assemble_document('Bid', fields)
    res = sign_and_store_document(rein, 'bid', document, user.daddr, user.dkey,
                                  store)
    if res and store:
        click.echo(
            "Bid created. Run 'rein sync' to push to available servers.")
    log.info('bid signed') if res else log.error('bid failed')