Example #1
0
def check_covert_component(msg, round_pubkey, component_feerate):
    message_hash = sha256(msg.component)
    check(len(msg.signature) == 64, "bad message signature")
    check(schnorr.verify(round_pubkey, msg.signature, message_hash), "bad message signature")

    cmsg = proto_strict_parse(pb.Component(), msg.component)
    check(len(cmsg.salt_commitment) == 32, "bad salt commitment")
    ctype = cmsg.WhichOneof('component')
    if ctype == 'input':
        inp = cmsg.input
        check(len(inp.prev_txid) == 32, "bad txid")
        check(   (len(inp.pubkey) == 33 and inp.pubkey[0] in (2,3))
              or (len(inp.pubkey) == 65 and inp.pubkey[0] == 4),
              "bad pubkey")
        sort_key = ('i', inp.prev_txid[::-1], inp.prev_index, cmsg.salt_commitment)
    elif ctype == 'output':
        out = cmsg.output
        atype, addr = get_address_from_output_script(out.scriptpubkey)
        check(atype == TYPE_ADDRESS, "output is not address")
        check(out.amount >= dust_limit(len(out.scriptpubkey)), "dust output")
        sort_key = ('o', out.amount, out.scriptpubkey, cmsg.salt_commitment)
    elif ctype == 'blank':
        sort_key = ('b', cmsg.salt_commitment)
    else:
        raise ValidationError('missing component details')

    # Note: for each sort type we use salt_commitment as a tie-breaker, just to
    # make sure that original ordering is forgotten. Of course salt_commitment
    # doesn't have to be unique, but it's unique for all honest players.

    return sort_key, component_contrib(cmsg, component_feerate)
Example #2
0
def tx_from_components(all_components, session_hash):
    """ Returns the tx and a list of indices matching inputs with components"""
    input_indices = []
    assert len(session_hash) == 32
    if Protocol.FUSE_ID is None:
        prefix = []
    else:
        assert len(Protocol.FUSE_ID) == 4
        prefix = [4, *Protocol.FUSE_ID]
    inputs = []
    outputs = [
        (TYPE_SCRIPT,
         ScriptOutput(bytes([OpCodes.OP_RETURN, *prefix, 32]) + session_hash),
         0)
    ]
    for i, compser in enumerate(all_components):
        comp = pb.Component()
        comp.ParseFromString(compser)
        ctype = comp.WhichOneof('component')
        if ctype == 'input':
            inp = comp.input
            if len(inp.prev_txid) != 32:
                raise FusionError("bad component prevout")
            inputs.append(
                dict(address=Address.from_P2PKH_hash(hash160(inp.pubkey)),
                     prevout_hash=inp.prev_txid[::-1].hex(),
                     prevout_n=inp.prev_index,
                     num_sig=1,
                     signatures=[None],
                     type='p2pkh',
                     x_pubkeys=[inp.pubkey.hex()],
                     pubkeys=[inp.pubkey.hex()],
                     sequence=0xffffffff,
                     value=inp.amount))
            input_indices.append(i)
        elif ctype == 'output':
            out = comp.output
            atype, addr = get_address_from_output_script(out.scriptpubkey)
            if atype != TYPE_ADDRESS:
                raise FusionError("bad component address")
            outputs.append((TYPE_ADDRESS, addr, out.amount))
        elif ctype != 'blank':
            raise FusionError("bad component")
    tx = Transaction.from_io(inputs, outputs, locktime=0, sign_schnorr=True)
    tx.version = 1
    return tx, input_indices