コード例 #1
0
def mktx( amt, tx_fee, recipient_addr, privkey, message=None ):
    """
    Make the transaction with the given fee
    """
    change_addr = virtualchain.BitcoinPrivateKey(privkey).public_key().address()
    inputs = testlib.get_unspents(change_addr)
    change = virtualchain.calculate_change_amount(inputs, amt, tx_fee)

    outputs = [
        {'script': virtualchain.make_payment_script(recipient_addr),
         'value': amt},
    ]

    if change > 0:
        # need change and tx fee
        outputs.append( 
            {'script': virtualchain.make_payment_script(change_addr),
              "value": change}
        )

    if message:
        outputs = [
            {"script": virtualchain.make_data_script(binascii.hexlify(message)),
             "value": 0} ] + outputs

    serialized_tx = blockstack_client.tx.serialize_tx(inputs, outputs)
    signed_tx = blockstack_client.tx.sign_tx(serialized_tx, privkey)
    return signed_tx
コード例 #2
0
def make_outputs( data, inputs, recipient_address, sender_address, update_hash_b58, tx_fee):
    """
    Builds the outputs for a name import:
    * [0] is the OP_RETURN 
    * [1] is the new owner (recipient)
    * [2] is the update hash
    * [3] is the change sent to the original owner

    Raise ValueError if there are not enough inputs to make the transaction
    """
    
    dust_fee = DEFAULT_OP_RETURN_FEE + (len(inputs) + 3) * DEFAULT_DUST_FEE + tx_fee
    op_fee = 2 * DEFAULT_DUST_FEE
    dust_value = DEFAULT_DUST_FEE
    
    return [
        # main output
        {"script": virtualchain.make_data_script(str(data)),
         "value": 0},
    
        # recipient output
        {"script": virtualchain.make_payment_script(recipient_address),
         "value": dust_value},
        
        # update hash output
        {"script": virtualchain.make_payment_script(update_hash_b58),
         "value": dust_value},
        
        # change output
        {"script": virtualchain.make_payment_script(sender_address),
         "value": virtualchain.calculate_change_amount(inputs, op_fee, dust_fee)}
    ]
コード例 #3
0
def make_outputs(data, inputs, reveal_addr, change_addr, tx_fee):
    """
    Make outputs for a register:
    [0] OP_RETURN with the name 
    [1] pay-to-address with the *reveal_addr*, not the sender's address.
    [2] change address with the NAMESPACE_PREORDER sender's address
    Raise ValueError if there are not enough inputs to make the transaction
    """

    total_to_send = DEFAULT_OP_RETURN_FEE + DEFAULT_DUST_FEE

    return [
        # main output
        {
            "script": virtualchain.make_data_script(str(data)),
            "value": 0
        },

        # register address
        {
            "script": virtualchain.make_payment_script(reveal_addr),
            "value": DEFAULT_DUST_FEE
        },

        # change address
        {
            "script":
            virtualchain.make_payment_script(change_addr),
            "value":
            virtualchain.calculate_change_amount(
                inputs, total_to_send,
                DEFAULT_DUST_FEE * (len(inputs) + 2) + DEFAULT_OP_RETURN_FEE +
                tx_fee)
        },
    ]
コード例 #4
0
def make_outputs( data, inputs, change_address, tx_fee, pay_fee=True ):
    """
    Make outputs for a revoke.
    Raise ValueError if there are not enough inputs to make the transaction
    """

    dust_fee = None
    op_fee = None
    dust_value = None 
    
    if pay_fee:
        dust_fee = (len(inputs) + 1) * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE + tx_fee
        op_fee = DEFAULT_DUST_FEE
        dust_value = DEFAULT_DUST_FEE
    
    else:
        # will be subsidized
        dust_fee = 0
        op_fee = 0
        dust_value = 0
   
    return [
        # main output
        {"script": virtualchain.make_data_script(str(data)),
         "value": 0},
        
        # change output
        {"script": virtualchain.make_payment_script(change_address),
         "value": virtualchain.calculate_change_amount(inputs, op_fee, dust_fee)}
    ]
コード例 #5
0
def make_outputs( data, inputs, new_name_owner_address, change_address, tx_fee=0, pay_fee=True):
    """
    Builds the outputs for a name transfer operation.
    Raise ValueError if there are not enough inputs to make the transaction
    """
    
    dust_fee = None
    op_fee = None
    dust_value = DEFAULT_DUST_FEE
    
    if pay_fee:
        dust_fee = (len(inputs) + 2) * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE + tx_fee
        op_fee = DEFAULT_DUST_FEE
    
    else:
        dust_fee = 0
        op_fee = 0
    
    return [
        # main output
        {"script": virtualchain.make_data_script(str(data)),
         "value": 0},
        # new name owner output
        {"script": virtualchain.make_payment_script(new_name_owner_address),
         "value": dust_value},
        # change output
        {"script": virtualchain.make_payment_script(change_address),
         "value": virtualchain.calculate_change_amount(inputs, op_fee, dust_fee)}
    ]
コード例 #6
0
def make_outputs( data, inputs, change_addr, fee, tx_fee, pay_fee=True ):
    """
    Make outputs for a namespace preorder:
    [0] OP_RETURN with the name 
    [1] change address with the NAME_PREORDER sender's address
    [2] pay-to-address with the *burn address* with the fee
    Raise ValueError if there are not enough inputs to make the transaction
    """
    
    dust_fee = DEFAULT_OP_RETURN_FEE + (len(inputs) + 2) * DEFAULT_DUST_FEE + tx_fee
    op_fee = max(fee, DEFAULT_DUST_FEE)
    
    bill = op_fee
   
    if not pay_fee:
        # subsidized
        dust_fee = 0
        op_fee = 0
        bill = 0
    
    return [
        # main output
        {"script": virtualchain.make_data_script(str(data)),
         "value": 0},
        
        # change address
        {"script": virtualchain.make_payment_script( change_addr ),
         "value": virtualchain.calculate_change_amount(inputs, bill, dust_fee)},
        
        # burn address
        {"script": virtualchain.make_payment_script(BLOCKSTACK_BURN_ADDRESS),
         "value": op_fee}
    ]
コード例 #7
0
def make_outputs( data, inputs, new_name_owner_address, change_address, tx_fee=0, pay_fee=True,
                  dust_included = False):
    """
    Builds the outputs for a name transfer operation.
    Raise ValueError if there are not enough inputs to make the transaction
    """

    dust_fee = None
    op_fee = None
    dust_value = DEFAULT_DUST_FEE

    if pay_fee:
        total_tx_fee = tx_fee
        if not dust_included:
            total_tx_fee += (len(inputs) + 2) * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE
        op_fee = DEFAULT_DUST_FEE
    else:
        total_tx_fee = 0
        op_fee = 0

    return [
        # main output
        {"script": virtualchain.make_data_script(str(data)),
         "value": 0},
        # new name owner output
        {"script": virtualchain.make_payment_script(new_name_owner_address),
         "value": dust_value},
        # change output
        {"script": virtualchain.make_payment_script(change_address),
         "value": virtualchain.calculate_change_amount(inputs, op_fee, total_tx_fee)}
    ]
コード例 #8
0
def make_outputs( data, inputs, change_address, tx_fee, pay_fee=True ):
    """
    Make outputs for a revoke.
    Raise ValueError if there are not enough inputs to make the transaction
    """

    dust_fee = None
    op_fee = None
    dust_value = None 
    
    if pay_fee:
        dust_fee = (len(inputs) + 1) * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE + tx_fee
        op_fee = DEFAULT_DUST_FEE
        dust_value = DEFAULT_DUST_FEE
    
    else:
        # will be subsidized
        dust_fee = 0
        op_fee = 0
        dust_value = 0
   
    return [
        # main output
        {"script": virtualchain.make_data_script(str(data)),
         "value": 0},
        
        # change output
        {"script": virtualchain.make_payment_script(change_address),
         "value": virtualchain.calculate_change_amount(inputs, op_fee, dust_fee)}
    ]
コード例 #9
0
def make_outputs(data,
                 inputs,
                 sender_addr,
                 burn_addr,
                 fee,
                 tx_fee,
                 pay_fee=True,
                 dust_included=False):
    """
    Make outputs for a name preorder:
    [0] OP_RETURN with the name
    [1] address with the NAME_PREORDER sender's address
    [2] pay-to-address with the *burn address* with the fee
    Raise ValueError if there are not enough inputs to make the transaction
    """

    op_fee = max(fee, DEFAULT_DUST_FEE)
    total_tx_fee = tx_fee
    if not dust_included:
        total_tx_fee += (len(inputs) +
                         2) * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE
    dust_value = DEFAULT_DUST_FEE

    bill = 0

    if pay_fee:
        bill = op_fee
    else:
        op_fee = 0
        bill = 0
        total_tx_fee = 0

    return [
        # main output
        {
            "script": virtualchain.make_data_script(str(data)),
            "value": 0
        },

        # change address (can be subsidy key)
        {
            "script":
            virtualchain.make_payment_script(str(sender_addr)),
            "value":
            virtualchain.calculate_change_amount(inputs, bill, total_tx_fee)
        },

        # burn address
        {
            "script": virtualchain.make_payment_script(str(burn_addr)),
            "value": op_fee
        }
    ]
コード例 #10
0
def make_outputs( nulldata, inputs, change_addr, tx_fee=0 ):
   """
   Make namespace-ready outputs
   """
   return [
        { "script": virtualchain.make_data_script(str(nulldata)),
          "value": 0
        },
        # change output
        { "script": virtualchain.make_payment_script(change_addr),
          "value": virtualchain.calculate_change_amount(inputs, 0, tx_fee + DEFAULT_OP_RETURN_FEE)
        }
    ]
コード例 #11
0
def make_outputs(nulldata, inputs, change_addr, tx_fee=0):
    """
   Make namespace-ready outputs
   """
    return [
        {
            "script": virtualchain.make_data_script(str(nulldata)),
            "value": 0
        },
        # change output
        {
            "script":
            virtualchain.make_payment_script(change_addr),
            "value":
            virtualchain.calculate_change_amount(
                inputs, 0, tx_fee + DEFAULT_OP_RETURN_FEE)
        }
    ]
コード例 #12
0
def make_outputs(data, inputs, change_addr, fee, tx_fee, pay_fee=True):
    """
    Make outputs for a namespace preorder:
    [0] OP_RETURN with the name 
    [1] change address with the NAME_PREORDER sender's address
    [2] pay-to-address with the *burn address* with the fee
    Raise ValueError if there are not enough inputs to make the transaction
    """

    dust_fee = DEFAULT_OP_RETURN_FEE + (len(inputs) +
                                        2) * DEFAULT_DUST_FEE + tx_fee
    op_fee = max(fee, DEFAULT_DUST_FEE)

    bill = op_fee

    if not pay_fee:
        # subsidized
        dust_fee = 0
        op_fee = 0
        bill = 0

    return [
        # main output
        {
            "script": virtualchain.make_data_script(str(data)),
            "value": 0
        },

        # change address
        {
            "script": virtualchain.make_payment_script(change_addr),
            "value":
            virtualchain.calculate_change_amount(inputs, bill, dust_fee)
        },

        # burn address
        {
            "script":
            virtualchain.make_payment_script(BLOCKSTACK_BURN_ADDRESS),
            "value": op_fee
        }
    ]
コード例 #13
0
def make_outputs( data, inputs, reveal_addr, change_addr, tx_fee):
    """
    Make outputs for a register:
    [0] OP_RETURN with the name 
    [1] pay-to-address with the *reveal_addr*, not the sender's address.
    [2] change address with the NAMESPACE_PREORDER sender's address
    Raise ValueError if there are not enough inputs to make the transaction
    """
    
    total_to_send = DEFAULT_OP_RETURN_FEE + DEFAULT_DUST_FEE
    
    return [
        # main output
        {"script": virtualchain.make_data_script(str(data)),
         "value": 0},
    
        # register address
        {"script": virtualchain.make_payment_script(reveal_addr),
         "value": DEFAULT_DUST_FEE},
        
        # change address
        {"script": virtualchain.make_payment_script(change_addr),
         "value": virtualchain.calculate_change_amount(inputs, total_to_send, DEFAULT_DUST_FEE * (len(inputs) + 2) + DEFAULT_OP_RETURN_FEE + tx_fee)},
    ]
コード例 #14
0
def make_outputs(data,
                 change_inputs,
                 register_addr,
                 change_addr,
                 tx_fee,
                 renewal_fee=None,
                 pay_fee=True):
    """
    Make outputs for a register:
    [0] OP_RETURN with the name 
    [1] pay-to-address with the *register_addr*, not the sender's address.
    [2] change address with the NAME_PREORDER sender's address
    [3] (OPTIONAL) renewal fee, sent to the burn address
    Raise ValueError if there are not enough inputs to make the transaction
    """

    dust_fee = None
    dust_value = DEFAULT_DUST_FEE
    op_fee = None
    bill = None

    if pay_fee:

        # sender pays
        if renewal_fee is not None:
            # renewing
            dust_fee = (len(change_inputs) +
                        3) * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE + tx_fee
            op_fee = max(renewal_fee, DEFAULT_DUST_FEE)
            bill = op_fee

        else:
            # registering
            dust_fee = (len(change_inputs) +
                        2) * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE + tx_fee
            op_fee = 0
            bill = DEFAULT_DUST_FEE * 2

    else:

        # subsidized by another address
        if renewal_fee is not None:
            # renewing
            dust_fee = 0
            op_fee = max(renewal_fee, DEFAULT_DUST_FEE)
            bill = 0

        else:
            # registering
            dust_fee = 0
            op_fee = 0
            bill = 0

    outputs = [
        # main output
        {
            "script": virtualchain.make_data_script(str(data)),
            "value": 0
        },

        # register address
        {
            "script": virtualchain.make_payment_script(register_addr),
            "value": dust_value
        },

        # change address (can be the subsidy address)
        {
            "script":
            virtualchain.make_payment_script(change_addr),
            "value":
            virtualchain.calculate_change_amount(change_inputs, bill, dust_fee)
        },
    ]

    if renewal_fee is not None:
        outputs.append(

            # burn address (when renewing)
            {
                "script":
                virtualchain.make_payment_script(BLOCKSTACK_BURN_ADDRESS),
                "value": op_fee
            })

    return outputs
def scenario(wallets, **kw):
    segwit_addr_1 = get_segwit_address(wallets[1].privkey)
    segwit_addr_1_tb = get_segwit_address(wallets[1].privkey, hrp='tb')
    segwit_addr_0_tb = get_segwit_address(wallets[0].privkey, hrp='tb')

    print segwit_addr_0_tb
    print segwit_addr_1_tb

    pubk = virtualchain.lib.ecdsalib.ecdsa_private_key(
        wallets[1].privkey, compressed=True).public_key().to_hex()
    addrhash = virtualchain.lib.hashing.bin_hash160(
        pubk.decode('hex')).encode('hex')

    a = 'tb1pzjpqjwmz5d5e9qkey6vphmtkvh5rsn9225xsgg79'
    namespace_preorder_name_hash = blockstack.lib.hashing.hash_name(
        'test', virtualchain.make_payment_script(wallets[0].addr), a)
    print 'hash of {} + {} + {} = {}'.format(
        'test', virtualchain.make_payment_script(wallets[0].addr), a,
        namespace_preorder_name_hash)

    resp = testlib.blockstack_namespace_preorder("test",
                                                 wallets[1].addr,
                                                 wallets[0].privkey,
                                                 tx_only=True)
    tx = virtualchain.btc_tx_deserialize(resp['transaction'])

    new_tx = {
        'locktime': 0,
        'version': 1,
        'ins': tx['ins'],
        'outs': tx['outs'],
    }

    for inp in new_tx['ins']:
        inp['script'] = ''
        inp['witness_script'] = ''

    print 'script before: {}'.format(tx['outs'][0]['script'])

    patched_script = virtualchain.make_data_script(
        'id*'.encode('hex') + namespace_preorder_name_hash +
        tx['outs'][0]['script'].decode('hex')[25:].encode('hex'))

    print 'script after : {}'.format(patched_script)

    new_tx['outs'][0] = {'script': patched_script, 'value': 0}

    unsigned_txhex = virtualchain.btc_tx_serialize(new_tx)
    print 'unsigned: {}'.format(unsigned_txhex)

    addr = virtualchain.address_reencode(
        virtualchain.get_privkey_address(wallets[0].privkey))
    utxos = testlib.get_utxos(addr)
    prev_outputs = [{
        'out_script': inp['out_script'],
        'value': inp['value']
    } for inp in utxos]

    signed_txhex = virtualchain.tx_sign_all_unsigned_inputs(
        wallets[0].privkey, prev_outputs, unsigned_txhex)

    print 'signed: {}'.format(signed_txhex)

    res = testlib.broadcast_transaction(signed_txhex)
    assert 'error' not in res

    testlib.next_block(**kw)

    # should fail
    resp = testlib.blockstack_namespace_reveal(
        "test",
        wallets[1].addr,
        52595,
        250,
        4, [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        10,
        10,
        wallets[0].privkey,
        tx_only=True)
    resp = replace_output_with_bech32(resp['transaction'], 1,
                                      wallets[0].privkey, addrhash)

    testlib.next_block(**kw)
コード例 #16
0
ファイル: register.py プロジェクト: zhilinwww/blockstack-core
def make_outputs(data,
                 change_inputs,
                 register_addr,
                 change_addr,
                 tx_fee,
                 renewal_fee=None,
                 burn_address=BLOCKSTACK_BURN_ADDRESS,
                 pay_fee=True,
                 dust_included=False):
    """
    Make outputs for a register:
    [0] OP_RETURN with the name, and possibly a value hash
    [1] pay-to-address with the *register_addr*, not the sender's address.  If renewing, this is the new owner address.
    [2] change address with the NAME_PREORDER or NAME_RENEWAL's subsidizer's sender's address
    [3] (OPTIONAL) renewal fee, sent to the burn address

    Raise ValueError if there are not enough inputs to make the transaction
    """

    dust_fee = None
    dust_value = DEFAULT_DUST_FEE
    op_fee = None
    bill = None

    if pay_fee:
        # sender pays
        total_tx_fee = tx_fee
        if renewal_fee is not None:
            # renewing
            dust_fee = (len(change_inputs) +
                        3) * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE
            op_fee = max(renewal_fee, DEFAULT_DUST_FEE)
            bill = op_fee
        else:
            # registering
            dust_fee = (len(change_inputs) +
                        2) * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE
            op_fee = 0
            bill = DEFAULT_DUST_FEE * 2
        if not dust_included:
            total_tx_fee += dust_fee
    else:
        # subsidized by another address
        bill = 0
        total_tx_fee = 0
        if renewal_fee is not None:
            # renewing
            op_fee = max(renewal_fee, DEFAULT_DUST_FEE)
        else:
            # registering
            op_fee = 0

    payload = str(data)

    outputs = [
        # main output
        {
            "script": virtualchain.make_data_script(payload),
            "value": 0
        },

        # register/new-owner address
        {
            "script": virtualchain.make_payment_script(str(register_addr)),
            "value": dust_value
        },

        # change address (can be the subsidy address)
        {
            "script":
            virtualchain.make_payment_script(str(change_addr)),
            "value":
            virtualchain.calculate_change_amount(change_inputs, bill,
                                                 total_tx_fee)
        },
    ]

    if renewal_fee is not None:
        outputs.append(
            # burn address (when renewing)
            {
                "script": virtualchain.make_payment_script(str(burn_address)),
                "value": op_fee
            })

    return outputs
コード例 #17
0
def parse_nameop( opcode, payload, fake_pubkey, recipient=None, recipient_address=None, import_update_hash=None, burn_address=None, reveal_address=None ):

    opcode_name = OPCODE_NAMES[opcode]
    pubk = virtualchain.BitcoinPublicKey(fake_pubkey)
    address = pubk.address()
    script_pubkey = virtualchain.make_payment_script( address )
    senders = [{
        "script_pubkey": script_pubkey,
        "script_type": "pubkeyhash",
        "addresses": [ address ]
    }]

    # just enough to get the public key
    inputs = [{
        'script': 'ignored {}'.format(fake_pubkey).encode('hex')
    }]

    script = "OP_RETURN %s" % payload

    try:
        scripthex = virtualchain.make_data_script(binascii.hexlify(payload))
    except:
        if len(payload) == 0:
            scripthex = "6a"
        else:
            print 'failed on {}'.format(payload)
            raise

    outputs = [{
        'script': scripthex,
        'value': 0
    }]

    if recipient_address is not None:
        script = "OP_DUP OP_HASH160 %s OP_EQUALVERIFY OP_CHECKSIG" % binascii.hexlify( virtualchain.lib.hashing.bin_double_sha256( fake_pubkey ) )
        scripthex = virtualchain.make_payment_script( recipient_address )
        outputs.append( {
            'script': scripthex,
            "value": 10000000
        })

    if import_update_hash is not None:
        script = "OP_DUP OP_HASH160 %s OP_EQUALVERIFY OP_CHECKSIG" % import_update_hash
        scripthex = virtualchain.make_payment_script( virtualchain.hex_hash160_to_address( import_update_hash ) )
        outputs.append( {
            "script": scripthex,
            "value": 10000000
        })

    elif burn_address is not None:
        scripthex = virtualchain.make_payment_script( burn_address )
        outputs.append( {
            "script": scripthex,
            "value": 10000000
        })
    
    elif reveal_address is not None:
        scripthex = virtualchain.make_payment_script( reveal_address )
        outputs.append( {
            "script": scripthex,
            "value": 10000000
        })

    try:
        op = op_extract( opcode_name, payload, senders, inputs, outputs, 488501, 0, "00" * 64 )  
    except AssertionError, ae:
        # failed to parse
        return None
コード例 #18
0
def make_outputs( data, change_inputs, register_addr, change_addr, tx_fee, renewal_fee=None, pay_fee=True):
    """
    Make outputs for a register:
    [0] OP_RETURN with the name 
    [1] pay-to-address with the *register_addr*, not the sender's address.
    [2] change address with the NAME_PREORDER sender's address
    [3] (OPTIONAL) renewal fee, sent to the burn address
    Raise ValueError if there are not enough inputs to make the transaction
    """
    
    dust_fee = None
    dust_value = DEFAULT_DUST_FEE
    op_fee = None
    bill = None 
    
    if pay_fee:
        
        # sender pays
        if renewal_fee is not None:
            # renewing
            dust_fee = (len(change_inputs) + 3) * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE + tx_fee
            op_fee = max(renewal_fee, DEFAULT_DUST_FEE)
            bill = op_fee
            
        else:
            # registering
            dust_fee = (len(change_inputs) + 2) * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE + tx_fee
            op_fee = 0
            bill = DEFAULT_DUST_FEE * 2
            
    else:
        
        # subsidized by another address
        if renewal_fee is not None:
            # renewing
            dust_fee = 0
            op_fee = max(renewal_fee, DEFAULT_DUST_FEE)
            bill = 0
            
        else:
            # registering
            dust_fee = 0
            op_fee = 0
            bill = 0
  
    outputs = [
        # main output
        {"script": virtualchain.make_data_script(str(data)),
         "value": 0},
    
        # register address
        {"script": virtualchain.make_payment_script(register_addr),
         "value": dust_value},
        
        # change address (can be the subsidy address)
        {"script": virtualchain.make_payment_script(change_addr),
         "value": virtualchain.calculate_change_amount(change_inputs, bill, dust_fee)},
    ]
    
    if renewal_fee is not None:
        outputs.append(
            
            # burn address (when renewing)
            {"script": virtualchain.make_payment_script(BLOCKSTACK_BURN_ADDRESS),
             "value": op_fee}
        )

    return outputs