Exemplo n.º 1
0
def parse_blinded_element(e):
    valid_key_sets = [
        {
            "asset_id_hex", "asset_blinder_hex", "amount_satoshi",
            "amount_blinder_hex"
        },
        {"asset_id_hex", "asset_blinder_hex"},
        {"amount_satoshi", "amount_blinder_hex", "asset_commitment_hex"},
    ]
    if not isinstance(e, dict):
        err("Should be a dict")
    if set(e.keys()) not in valid_key_sets:
        err("Invalid keys")

    if "asset_id_hex" in e:
        asset_commitment_bin = wally.asset_generator_from_bytes(
            parse_uint256_hex(e["asset_id_hex"]),
            parse_uint256_hex(e["asset_blinder_hex"]))
    else:
        asset_commitment_bin = parse_commitment_hex(e["asset_commitment_hex"])

    if "amount_satoshi" in e:
        amount_commitment_bin = wally.asset_value_commitment(
            parse_sat(e["amount_satoshi"]),
            parse_uint256_hex(e["amount_blinder_hex"]), asset_commitment_bin)
    else:
        amount_commitment_bin = None

    return {
        "asset_id_hex": e.get("asset_id_hex"),
        "asset_commitment_bin": asset_commitment_bin,
        "amount_satoshi": e.get("amount_satoshi"),
        "amount_commitment_bin": amount_commitment_bin,
    }
Exemplo n.º 2
0
    def _get_blinding_factors(self, txdetails, wally_tx):
        utxos = txdetails['used_utxos'] or txdetails['old_used_utxos']

        for i, o in enumerate(txdetails['transaction_outputs']):
            o['wally_index'] = i

        blinded_outputs = [
            o for o in txdetails['transaction_outputs'] if not o['is_fee']
        ]
        for output in blinded_outputs:
            # TODO: the derivation dance
            # the following values are in display order, reverse them when converting to bytes
            output['assetblinder'] = os.urandom(32).hex()
            output['amountblinder'] = os.urandom(32).hex()

        endpoints = utxos + blinded_outputs
        values = [endpoint['satoshi'] for endpoint in endpoints]
        abfs = b''.join(
            bytes.fromhex(endpoint['assetblinder'])[::-1]
            for endpoint in endpoints)
        vbfs = b''.join(
            bytes.fromhex(endpoint['amountblinder'])[::-1]
            for endpoint in endpoints[:-1])
        final_vbf = wally.asset_final_vbf(values, len(utxos), abfs, vbfs)
        blinded_outputs[-1]['amountblinder'] = final_vbf[::-1].hex()

        for o in blinded_outputs:
            asset_commitment = wally.asset_generator_from_bytes(
                bytes.fromhex(o['asset_id'])[::-1],
                bytes.fromhex(o['assetblinder'])[::-1])
            value_commitment = wally.asset_value_commitment(
                o['satoshi'],
                bytes.fromhex(o['amountblinder'])[::-1], asset_commitment)

            o['asset_commitment'] = asset_commitment.hex()
            o['value_commitment'] = value_commitment.hex()

            # Write the commitments into the wally tx for signing
            wally.tx_set_output_asset(wally_tx, o['wally_index'],
                                      asset_commitment)
            wally.tx_set_output_value(wally_tx, o['wally_index'],
                                      value_commitment)

        retval = {}
        for key in [
                'assetblinders', 'amountblinders', 'asset_commitments',
                'value_commitments'
        ]:
            # gdk expects to get an empty entry for the fee output too, hence this is over the
            # transaction outputs, not just the blinded outputs (fee will just have empty
            # strings)
            retval[key] = [
                o.get(key[:-1], '') for o in txdetails['transaction_outputs']
            ]
        return retval
Exemplo n.º 3
0
def parse_blinded_element_v0(e):
    asset_commitment_bin = None
    amount_commitment_bin = None
    if len(e.keys()) == 5:
        asset_commitment_bin = wally.asset_generator_from_bytes(
            parse_uint256_hex(e["asset_id"]),
            parse_uint256_hex(e["assetblinder"]))
        amount_commitment_bin = wally.asset_value_commitment(
            parse_sat(e["satoshi"]), parse_uint256_hex(e["amountblinder"]),
            asset_commitment_bin)

    return {
        "asset_id_hex": e.get("asset_id"),
        "asset_commitment_bin": asset_commitment_bin,
        "amount_satoshi": e.get("satoshi"),
        "amount_commitment_bin": amount_commitment_bin,
    }
Exemplo n.º 4
0
locktime = 0
output_tx = wally.tx_init(version, locktime, 0, 0)
# end-create_output_tx

# start-create_outputs
for value, blinding_pubkey, script_pubkey in zip(output_values,
                                                 blinding_pubkeys,
                                                 script_pubkeys):

    abf, abfs_out = abfs_out[:32], abfs_out[32:]
    vbf, vbfs_out = vbfs_out[:32], vbfs_out[32:]
    asset_id, output_asset_ids = output_asset_ids[:32], output_asset_ids[32:]

    generator = wally.asset_generator_from_bytes(asset_id, abf)

    value_commitment = wally.asset_value_commitment(value, vbf, generator)

    ephemeral_privkey = os.urandom(32)
    ephemeral_pubkey = wally.ec_public_key_from_private_key(ephemeral_privkey)

    rangeproof = wally.asset_rangeproof(
        value,
        blinding_pubkey,
        ephemeral_privkey,
        asset_id,
        abf,
        vbf,
        value_commitment,
        script_pubkey,
        generator,
        1,  # min_value
Exemplo n.º 5
0
def main():
    parser = argparse.ArgumentParser()

    parser.add_argument(
        "-n",
        "--node-url",
        help="Elements node URL, eg http://USERNAME:PASSWORD@HOST:PORT/",
        required=True)
    parser.add_argument("-u", "--utxo", help="txid:vout", required=True)
    parser.add_argument("-a",
                        "--asset",
                        help="asset to receive",
                        required=True)
    parser.add_argument("-r",
                        "--rate",
                        type=float,
                        help="price_asset_send/price_asset_receive",
                        required=True)

    args = parser.parse_args()

    txid, vout = args.utxo.split(":")
    vout = int(vout)
    asset_receive, rate = args.asset, args.rate

    connection = RPCHost(args.node_url)

    unspents = connection.call("listunspent")
    utxo = [u for u in unspents if u["txid"] == txid and u["vout"] == vout][0]

    amount_receive = round(rate * utxo["amount"], 8)
    address = connection.call("getnewaddress")

    tx = connection.call("createrawtransaction", [{
        "txid": txid,
        "vout": vout,
        "sequence": 0xffffffff
    }], {address: amount_receive}, 0, False, {address: asset_receive})

    asset_blinder_bytes = os.urandom(32)
    amount_blinder_bytes = os.urandom(32)
    asset_commitment = wally.asset_generator_from_bytes(
        h2b_rev(asset_receive), asset_blinder_bytes)
    amount_commitment = wally.asset_value_commitment(btc2sat(amount_receive),
                                                     amount_blinder_bytes,
                                                     asset_commitment)

    tx_ = wally.tx_from_hex(
        tx, wally.WALLY_TX_FLAG_USE_WITNESS | wally.WALLY_TX_FLAG_USE_ELEMENTS)
    wally.tx_set_output_asset(tx_, 0, asset_commitment)
    wally.tx_set_output_value(tx_, 0, amount_commitment)
    tx = wally.tx_to_hex(
        tx_,
        wally.WALLY_TX_FLAG_USE_WITNESS | wally.WALLY_TX_FLAG_USE_ELEMENTS)

    ret = connection.call("signrawtransactionwithwallet", tx, None,
                          "SINGLE|ANYONECANPAY")

    assert ret["complete"]
    print(
        json.dumps(
            {
                "tx":
                ret["hex"],
                "inputs": [{
                    "asset": utxo["asset"],
                    "amount": btc2sat(utxo["amount"]),
                    "asset_blinder": utxo["assetblinder"],
                    "amount_blinder": utxo["amountblinder"],
                }],
                "outputs": [{
                    "asset": asset_receive,
                    "amount": btc2sat(amount_receive),
                    "asset_blinder": b2h_rev(asset_blinder_bytes),
                    "amount_blinder": b2h_rev(amount_blinder_bytes),
                }],
            },
            separators=(',', ':')))