Example #1
0
def make_outputs( data, inputs, recipient_address, sender_address, update_hash_b58, format='bin'):
    """
    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
    """
    
    dust_value = DEFAULT_DUST_FEE
    
    outputs = [
        # main output
        {"script_hex": make_op_return_script(data, format=format),
         "value": 0},
    
        # recipient output
        {"script_hex": make_pay_to_address_script(recipient_address),
         "value": dust_value},
        
        # update hash output
        {"script_hex": make_pay_to_address_script(update_hash_b58),
         "value": dust_value},
        
        # change output
        {"script_hex": make_pay_to_address_script(sender_address),
         "value": calculate_change_amount(inputs, 0, 0)}
    ]

    dust_fee = tx_dust_fee_from_inputs_and_outputs( inputs, outputs )
    outputs[-1]['value'] = calculate_change_amount( inputs, 2*dust_value, dust_fee )
    return outputs
def check( state_engine ):

    global transfer_block 

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        return False 

    if ns['namespace_id'] != 'test':
        return False 

    # not preordered 
    for i in xrange(0, len(wallets)):
        preorder = state_engine.get_name_preorder( "foo.test", pybitcoin.make_pay_to_address_script(wallets[i].addr), wallets[(i+1)%5].addr )
        if preorder is not None:
            print "preordered"
            return False

    # registered 
    name_rec = state_engine.get_name( "foo.test" )
    if name_rec is None:
        print "no name"
        return False 

    # owned by
    if name_rec['address'] != wallets[8].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallets[8].addr):
        print "address/sender is wrong: got %s, %s" % (name_rec['address'], name_rec['sender'])
        return False

    # has new sender pubkey (from the payment key)
    if name_rec['sender_pubkey'] != wallets[7].pubkey_hex:
        print "wrong pubkey: %s != %s" % (name_rec['sender_pubkey'], wallets[7].pubkey_hex)
        return False

    # has no value hash 
    if name_rec['value_hash'] is not None:
        print "still has value hash"
        return False

    # transfer happened
    historic_name_rec = state_engine.get_name_at( "foo.test", transfer_block, include_expired=True )
    if historic_name_rec is None or len(historic_name_rec) == 0:
        print "no name at %s" % transfer_block
        return False

    historic_name_rec = historic_name_rec[0]
    if historic_name_rec['opcode'] != "NAME_TRANSFER":
        print "transfer didn't occur at %s" % transfer_block
        return False

    if historic_name_rec['address'] != wallets[4].addr or historic_name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallets[4].addr):
        print "address/sender is wrong for transfer: got %s, %s" % (name_rec['address'], name_rec['sender'])
        return False

    return True
def check( state_engine ):

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        print "'test' not revealed"
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        print "'test' not found"
        return False 

    if ns['namespace_id'] != 'test':
        print "'test' not returned"
        return False 

    # not preordered
    preorder = state_engine.get_name_preorder( "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr), wallets[3].addr )
    if preorder is not None:
        print "'foo.test' still preordered"
        return False
    
    # registered 
    name_rec = state_engine.get_name( "foo.test" )
    if name_rec is None:
        print "'foo.test' not registered"
        return False 

    # transferred 
    if name_rec['address'] != wallets[4].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallets[4].addr):
        print "'foo.test' invalid owner"
        return False 

    return True
Example #4
0
def make_outputs( data, inputs, sender_addr, fee, format='bin' ):
    """
    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
    """
    
    op_fee = max(fee, DEFAULT_DUST_FEE)
    dust_fee = (len(inputs) + 2) * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE
    dust_value = DEFAULT_DUST_FEE
     
    bill = op_fee
    
    return [
        # main output
        {"script_hex": make_op_return_script(data, format=format),
         "value": 0},
        
        # change address (can be subsidy key)
        {"script_hex": make_pay_to_address_script(sender_addr),
         "value": calculate_change_amount(inputs, bill, dust_fee)},
        
        # burn address
        {"script_hex": make_pay_to_address_script(BLOCKSTORE_BURN_ADDRESS),
         "value": op_fee}
    ]
def make_outputs( data, inputs, change_addr, op_fee, format='bin' ):
    """
    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
    """
   
    op_fee = max( op_fee, DEFAULT_DUST_FEE )

    outputs =  [
        # main output
        {"script_hex": make_op_return_script(data, format=format),
         "value": 0},
        
        # change address
        {"script_hex": make_pay_to_address_script(change_addr),
         "value": calculate_change_amount(inputs, 0, 0)},
        
        # burn address
        {"script_hex": make_pay_to_address_script(BLOCKSTORE_BURN_ADDRESS),
         "value": op_fee}
    ]
    
    dust_fee = tx_dust_fee_from_inputs_and_outputs( inputs, outputs )
    outputs[1]['value'] = calculate_change_amount( inputs, op_fee, dust_fee )

    return outputs 
def check(state_engine):

    # not revealed, but ready
    ns = state_engine.get_namespace_reveal("test")
    if ns is not None:
        return False

    ns = state_engine.get_namespace("test")
    if ns is None:
        return False

    if ns["namespace_id"] != "test":
        return False

    # not preordered
    preorder = state_engine.get_name_preorder(
        "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr), wallets[3].addr
    )
    if preorder is not None:
        return False

    # registered
    name_rec = state_engine.get_name("foo.test")
    if name_rec is None:
        return False

    # owned by
    if name_rec["address"] != wallets[3].addr or name_rec["sender"] != pybitcoin.make_pay_to_address_script(
        wallets[3].addr
    ):
        return False

    return True
def make_outputs( data, inputs, new_name_owner_address, change_address, pay_fee=True, format='bin' ):
    """
    Builds the outputs for a name transfer operation.
    """
    
    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
        op_fee = DEFAULT_DUST_FEE
    
    else:
        dust_fee = 0
        op_fee = 0
    
    return [
        # main output
        {"script_hex": make_op_return_script(data, format=format),
         "value": 0},
        # new name owner output
        {"script_hex": make_pay_to_address_script(new_name_owner_address),
         "value": dust_value},
        # change output
        {"script_hex": make_pay_to_address_script(change_address),
         "value": calculate_change_amount(inputs, op_fee, dust_fee)}
    ]
Example #8
0
def make_outputs( data, inputs, sender_addr, op_fee, format='bin' ):
    """
    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
    
    NOTE: the fee must cover *all* the names
    """
    
    outputs = [
        # main output
        {"script_hex": make_op_return_script(data, format=format),
         "value": 0},
        
        # change address (can be subsidy key)
        {"script_hex": make_pay_to_address_script(sender_addr),
         "value": calculate_change_amount(inputs, 0, 0)},
        
        # burn address
        {"script_hex": make_pay_to_address_script(BLOCKSTORE_BURN_ADDRESS),
         "value": op_fee}
    ]

    dust_fee = tx_dust_fee_from_inputs_and_outputs( inputs, outputs )
    outputs[1]['value'] = calculate_change_amount( inputs, op_fee, dust_fee )
    return outputs
def check( state_engine ):

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        return False 

    if ns['namespace_id'] != 'test':
        return False 

    # not preordered
    preorder = state_engine.get_name_preorder( "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr), wallets[3].addr )
    if preorder is not None:
        return False
    
    # registered 
    name_rec = state_engine.get_name( "foo.test" )
    if name_rec is None:
        return False 

    # updated, and data is preserved
    if name_rec['value_hash'] != '11' * 20:
        return False 

    # transferred 
    if name_rec['address'] != wallets[4].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallets[4].addr):
        return False 

    return True
Example #10
0
def make_outputs( data, inputs, reveal_addr, change_addr, format='bin', testset=False ):
    """
    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
    """
    
    outputs = [
        # main output
        {"script_hex": make_op_return_script(data, format=format),
         "value": 0},
    
        # register address
        {"script_hex": make_pay_to_address_script(reveal_addr),
         "value": DEFAULT_DUST_FEE},
        
        # change address
        {"script_hex": make_pay_to_address_script(change_addr),
         "value": calculate_change_amount(inputs, 0, 0)},
    ]

    dust_fee = tx_dust_fee_from_inputs_and_outputs( inputs, outputs )
    outputs[-1]['value'] = calculate_change_amount( inputs, DEFAULT_DUST_FEE, dust_fee )
    return outputs
def make_outputs( data, inputs, change_addr, fee, pay_fee=True, format='bin' ):
    """
    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
    """
    
    dust_fee = DEFAULT_OP_RETURN_FEE + (len(inputs) + 2) * DEFAULT_DUST_FEE
    op_fee = max(fee, DEFAULT_DUST_FEE)
    dust_value = DEFAULT_DUST_FEE
    
    bill = op_fee
   
    if not pay_fee:
        # subsidized
        dust_fee = 0
        op_fee = 0
        dust_value = 0
        bill = 0
    
    return [
        # main output
        {"script_hex": make_op_return_script(data, format=format),
         "value": 0},
        
        # change address
        {"script_hex": make_pay_to_address_script(change_addr),
         "value": calculate_change_amount(inputs, bill, dust_fee)},
        
        # burn address
        {"script_hex": make_pay_to_address_script(BLOCKSTORE_BURN_ADDRESS),
         "value": op_fee}
    ]
def check( state_engine ):

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        return False 

    if ns['namespace_id'] != 'test':
        return False 

    # not preordered
    preorder = state_engine.get_name_preorder( "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr), wallets[3].addr )
    if preorder is not None:
        return False
    
    # registered 
    name_rec = state_engine.get_name( "foo.test" )
    if name_rec is None:
        return False

    # owned by
    if name_rec['address'] != wallets[3].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallets[3].addr):
        return False

    # NOT renewed
    if name_rec['last_renewed'] != name_rec['first_registered']:
        print name_rec['last_renewed']
        print name_rec['first_registered']
        return False

    return True
def check( state_engine ):

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "id" )
    if ns is not None:
        print "namespace reveal exists"
        return False 

    ns = state_engine.get_namespace( "id" )
    if ns is None:
        print "no namespace"
        return False 

    if ns['namespace_id'] != 'id':
        print "wrong namespace"
        return False 

    # not preordered
    preorder = state_engine.get_name_preorder( "foo.id", pybitcoin.make_pay_to_address_script(wallets[2].addr), wallets[3].addr )
    if preorder is not None:
        print "preorder exists"
        return False
    
    # registered 
    name_rec = state_engine.get_name( "foo.id" )
    if name_rec is None:
        print "name does not exist"
        return False 

    # owned by
    if name_rec['address'] != wallets[3].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallets[3].addr):
        print "sender is wrong"
        return False 

    return True
def check( state_engine ):

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        return False 

    if ns['namespace_id'] != 'test':
        return False 

    # not preordered
    preorder = state_engine.get_name_preorder( "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr), wallets[3].addr )
    if preorder is not None:
        print json.dumps(name_rec, indent=4)
        return False
    
    # registered to new owner
    name_rec = state_engine.get_name( "foo.test" )
    if name_rec is None:
        print "name rec is None"
        return False 

    if name_rec['address'] != wallets[3].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallets[3].addr):
        print json.dumps(name_rec, indent=4 )
        return False

    return True
def do_interleaving( name, namerecs, order ):
    
    # order should be a string of "u", "t", and "r"
    order = list(order)
    
    for i in xrange(0, len(order)):
    
        op = order[i]

        if op == 'r':
            # renew
            print "\nrenew '%s' with %s\n" % (name, pybitcoin.make_pay_to_address_script( namerecs[name][0].addr ))
            resp = testlib.blockstack_name_renew( name, namerecs[name][0].privkey, register_addr=namerecs[name][0].addr )
            if 'error' in resp:
                print json.dumps( resp, indent=4 )

        elif op == 'u':
            # update
            resp = testlib.blockstack_name_update( name, ("%s%s" % (i, i)) * 20, namerecs[name][0].privkey )
            if 'error' in resp:
                print json.dumps( resp, indent=4 )

        elif op == 't':
            # transfer and exchange wallets 
            print "\ntransfer '%s' from %s to %s" % (name, pybitcoin.make_pay_to_address_script( namerecs[name][0].addr ), pybitcoin.make_pay_to_address_script( namerecs[name][1].addr ))
            resp = testlib.blockstack_name_transfer( name, namerecs[name][1].addr, True, namerecs[name][0].privkey )
            if 'error' in resp:
                print json.dumps( resp, indent=4 )

            tmp = namerecs[name][0]
            namerecs[name][0] = namerecs[name][1]
            namerecs[name][1] = tmp
Example #16
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_hex": make_op_return_script(str(data), format='hex'),
         "value": 0},
    
        # recipient output
        {"script_hex": make_pay_to_address_script(recipient_address),
         "value": dust_value},
        
        # update hash output
        {"script_hex": make_pay_to_address_script(update_hash_b58),
         "value": dust_value},
        
        # change output
        {"script_hex": make_pay_to_address_script(sender_address),
         "value": calculate_change_amount(inputs, op_fee, dust_fee)}
    ]
def make_outputs( data, inputs, recipient_address, sender_address, update_hash_b58, format='bin'):
    """
    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
    """
    
    dust_fee = DEFAULT_OP_RETURN_FEE + (len(inputs) + 3) * DEFAULT_DUST_FEE
    op_fee = 2 * DEFAULT_DUST_FEE
    dust_value = DEFAULT_DUST_FEE
    
    return [
        # main output
        {"script_hex": make_op_return_script(data, format=format),
         "value": 0},
    
        # recipient output
        {"script_hex": make_pay_to_address_script(recipient_address),
         "value": dust_value},
        
        # update hash output
        {"script_hex": make_pay_to_address_script(update_hash_b58),
         "value": dust_value},
        
        # change output
        {"script_hex": make_pay_to_address_script(sender_address),
         "value": calculate_change_amount(inputs, op_fee, dust_fee)}
    ]
Example #18
0
def make_outputs( data, inputs, register_addr, change_addr, renewal_fee=None, format='bin' ):
    """
    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
    """
    
    total_to_send = DEFAULT_OP_RETURN_FEE + DEFAULT_DUST_FEE
    if renewal_fee is not None:
        total_to_send += max(renewal_fee, DEFAULT_DUST_FEE)
    
    outputs = [
        # main output
        {"script_hex": make_op_return_script(data, format=format),
         "value": DEFAULT_OP_RETURN_FEE},
    
        # register address
        {"script_hex": make_pay_to_address_script(register_addr),
         "value": DEFAULT_DUST_FEE},
        
        # change address
        {"script_hex": make_pay_to_address_script(change_addr),
         "value": calculate_change_amount(inputs, total_to_send, (len(inputs) + 3) * DEFAULT_DUST_FEE)},
    ]
    
    if renewal_fee is not None:
        outputs.append(
            
            # burn address (when renewing)
            {"script_hex": make_pay_to_address_script(BLOCKSTORE_BURN_ADDRESS),
             "value": max(renewal_fee, DEFAULT_DUST_FEE)}
        )

    return outputs
Example #19
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_hex": make_op_return_script(str(data), format='hex'),
         "value": 0},
        # new name owner output
        {"script_hex": make_pay_to_address_script(new_name_owner_address),
         "value": dust_value},
        # change output
        {"script_hex": make_pay_to_address_script(change_address),
         "value": calculate_change_amount(inputs, op_fee, dust_fee)}
    ]
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)
    dust_value = DEFAULT_DUST_FEE
    
    bill = op_fee
   
    if not pay_fee:
        # subsidized
        dust_fee = 0
        op_fee = 0
        dust_value = 0
        bill = 0
    
    return [
        # main output
        {"script_hex": make_op_return_script(str(data), format='hex'),
         "value": 0},
        
        # change address
        {"script_hex": make_pay_to_address_script(change_addr),
         "value": calculate_change_amount(inputs, bill, dust_fee)},
        
        # burn address
        {"script_hex": make_pay_to_address_script(BLOCKSTACK_BURN_ADDRESS),
         "value": op_fee}
    ]
def check(state_engine):

    # not revealed, but ready
    ns = state_engine.get_namespace_reveal("test")
    if ns is not None:
        return False

    ns = state_engine.get_namespace("test")
    if ns is None:
        return False

    if ns["namespace_id"] != "test":
        return False

    names = ["foo.test", "bar.test", "baz.test"]
    name_preorder_wallets = [wallets[2], wallets[3], wallets[4]]
    name_register_wallets = [wallets[5], wallets[6], wallets[7]]
    name_transfer_wallets = [wallets[6], wallets[7], wallets[5]]

    for i in xrange(0, len(names)):

        name = names[i]
        name_preorder_wallet = name_preorder_wallets[i]
        name_register_wallet = name_register_wallets[i]
        name_transfer_wallet = name_transfer_wallets[i]

        # not preordered
        preorder = state_engine.get_name_preorder(
            name, pybitcoin.make_pay_to_address_script(name_preorder_wallet.addr), name_register_wallet.addr
        )
        if preorder is not None:
            print "%s still preordered" % name
            return False

        # registered
        name_rec = state_engine.get_name(name)
        if name_rec is None:
            print "not registered %s" % name
            return False

        # updated, and data is gone (since revoked)
        if name_rec["value_hash"] is not None:
            print "invalid value hash %s: %s" % (name, name_rec["value_hash"])
            return False

        # owned by the right transfer wallet
        if name_rec["address"] != name_transfer_wallet.addr or name_rec[
            "sender"
        ] != pybitcoin.make_pay_to_address_script(name_transfer_wallet.addr):
            print "%s owned by %s" % (name, name_transfer_wallet.addr)
            return False

        # revoked
        if not name_rec["revoked"]:
            print "%s not revoked" % name
            return False

    return True
def check( state_engine ):

    global wallet_keys, datasets, zonefile_hash

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        print "namespace not ready"
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        print "no namespace"
        return False 

    if ns['namespace_id'] != 'test':
        print "wrong namespace"
        return False 

    # not preordered
    preorder = state_engine.get_name_preorder( "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr), wallets[3].addr )
    if preorder is not None:
        print "still have preorder"
        return False
    
    # registered 
    name_rec = state_engine.get_name( "foo.test" )
    if name_rec is None:
        print "name does not exist"
        return False 

    # owned 
    if name_rec['address'] != wallets[3].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallets[3].addr):
        print "name has wrong owner"
        return False 

    # have right hash 
    if name_rec['value_hash'] != zonefile_hash:
        print "Invalid zonefile hash"
        return False 

    # have no data
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )

    for i in xrange(0, len(datasets)):
        print "get hello_world_%s" % (i+1)
        dat = blockstack_client.get_mutable( "foo.test", "hello_world_%s" % (i+1) )
        if dat is not None and 'error' not in dat:
            print "still have '%s'\n%s" % ("hello_world_%s" % (i+1), json.dumps(dat,indent=4,sort_keys=True))
            return False

        if 'error' in dat and dat['error'] != 'No such mutable datum':
            print json.dumps(dat, indent=4, sort_keys=True)
            return False
    
    return True
def check( state_engine ):

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        return False 

    if ns['namespace_id'] != 'test':
        return False 

    # not preordered
    preorder = state_engine.get_name_preorder( "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr), wallets[3].addr )
    if preorder is not None:
        return False
    
    # registered 
    name_rec = state_engine.get_name( "foo.test" )
    if name_rec is None:
        return False 

    # owned 
    if name_rec['address'] != wallets[4].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallets[4].addr):
        return False 

    # not updated
    if name_rec['value_hash'] is not None:
        print "value hash is %s" % name_rec['value_hash']
        return False 

    # not transferred 
    if name_rec['address'] != wallets[4].addr:
        print "address is %s" % name_rec['address']
        return False 

    # TODO: check renewal block
    # no longer revoked 
    if name_rec['revoked']:
        return False 

    # at each of the fail blocks, confirm that the name has not changed from the initial revocation
    for fb in fail_blocks:
        historic_name_rec = state_engine.get_name_at( "foo.test", fb, include_expired=True )
        if historic_name_rec is None or len(historic_name_rec) == 0:
            print "no name at %s" % fb
            return False

        historic_name_rec = historic_name_rec[0]
        if historic_name_rec['opcode'] != 'NAME_REVOKE':
            print "accepted opcode %s at %s" % (historic_name_rec['opcode'], fb)
            return False

    return True
def check( state_engine ):

    global update_hashes, update_blocks 

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        return False 

    if ns['namespace_id'] != 'test':
        return False 

    # not preordered
    preorder = state_engine.get_name_preorder( "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr), wallets[3].addr )
    if preorder is not None:
        print json.dumps(name_rec, indent=4)
        return False
    
    # registered to new owner
    name_rec = state_engine.get_name( "foo.test" )
    if name_rec is None:
        print "name rec is None"
        return False 

    # updated 
    if name_rec['value_hash'] != '0a' * 20:
        print "invalid value hash"
        return False 

    if name_rec['address'] != wallets[0].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallets[0].addr):
        print json.dumps(name_rec, indent=4 )
        return False

    # updated historically too 
    for i in xrange(0, len(update_blocks)):
        update_block = update_blocks[i]
        update_hash = update_hashes[i]
        historic_name_rec = state_engine.get_name_at( "foo.test", update_block, include_expired=True )
        if historic_name_rec is None or len(historic_name_rec) == 0:
            print "no name at %s" % update_block
            return False

        historic_name_rec = historic_name_rec[0]
        if historic_name_rec['opcode'] != 'NAME_UPDATE':
            print "not an update at %s" % update_block
            return False

        if historic_name_rec.get('value_hash', None) != update_hash:
            print "wrong update hash at %s: expected %s, got %s" % (update_block, historic_name_rec.get('value_hash', None), update_hash)
            return False

    return True
def check( state_engine ):

    global import_block 

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        return False 

    if ns['namespace_id'] != 'test':
        return False 

    # not preordered 
    for i in xrange(0, len(wallets)):
        preorder = state_engine.get_name_preorder( "foo.test", pybitcoin.make_pay_to_address_script(wallets[i].addr), wallets[(i+1)%5].addr )
        if preorder is not None:
            print "preordered"
            return False

    # registered 
    name_rec = state_engine.get_name( "foo.test" )
    if name_rec is None:
        print "no name"
        return False 

    # owned by
    if name_rec['address'] != wallets[8].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallets[8].addr):
        print "sender is wrong"
        return False

    # has new sender pubkey (from the payment key)
    if name_rec['sender_pubkey'] != wallets[7].pubkey_hex:
        print "wrong pubkey: %s != %s" % (name_rec['sender_pubkey'], wallets[7].pubkey_hex)
        return False

    # verify historic owner and value hash 
    historic_name_rec = state_engine.get_name_at( "foo.test", import_block, include_expired=True )
    if historic_name_rec is None or len(historic_name_rec) == 0:
        print "no name at %s" % import_block
        return False

    historic_name_rec = historic_name_rec[0]
    if not historic_name_rec.has_key('value_hash') or historic_name_rec['value_hash'] != '11' * 20:
        print "wrong historic name import value hash: %s" % historic_name_rec.get("value_hash", "(null)")
        return False

    if historic_name_rec['address'] != wallets[3].addr or historic_name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallets[3].addr):
        print "historic sender is wrong"
        return False

    return True
def check( state_engine ):

    global preorder_consensus

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        return False 

    if ns['namespace_id'] != 'test':
        return False 

    # there won't be a preorder for an individual name...
    preorder = state_engine.get_name_preorder( "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr), wallets[3].addr )
    if preorder is not None:
        print "found name preorder for 'foo.test'"
        return False
   
    # there won't be a preorder for all names either
    preorder = state_engine.get_name_multi_preorder( ['foo.test', 'bar.test', 'baz.test'], \
                                                     pybitcoin.make_pay_to_address_script(wallets[2].addr), \
                                                     [wallets[3].addr, wallets[4].addr, wallets[5].addr])

    if preorder is not None:
        print "Preorder found for foo.test, bar.test, baz.test"
        return False

    prev_name_rec = None
    # each name will be registered 
    for name, wallet in [('foo.test', wallets[3]), ('bar.test', wallets[4]), ('baz.test', wallets[5])]:

        name_rec = state_engine.get_name( name )
        if name_rec is None:
            print "No name record for %s" % name
            return False 

        if name_rec['address'] != wallet.addr:
            print "'%s' not owned by '%s'" % (name, wallet.addr)
            return False 

        if name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallet.addr):
            print "'%s' not controlled by '%s'" % (name, pybitcoin.make_pay_to_address_script(wallet.addr))
            return False

        if prev_name_rec is not None and prev_name_rec['history'] != name_rec['history']:
            print "'%s' does not have the same preorder as '%s'" % (prev_name_rec['name'], name_rec['name'])
            return False 

        prev_name_rec = name_rec

        return True
def check( state_engine ):

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        return False 

    if ns['namespace_id'] != 'test':
        return False 

    # there won't be a preorder for an individual name...
    preorder = state_engine.get_name_preorder( "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr), wallets[3].addr )
    if preorder is not None:
        print "found name preorder for 'foo.test'"
        return False
   
    # there will be a preorder for all names
    preorder = state_engine.get_name_preorder_multi( ['foo.test', 'bar.test', 'baz.test'], \
                                                     pybitcoin.make_pay_to_address_script(wallets[2].addr), \
                                                     [wallets[3].addr, wallets[4].addr, wallets[5].addr])

    if preorder is None:
        print "Preorder not found for foo.test, bar.test, baz.test"
        return False

    prev_name_rec = None

    # none of the multi-preordered names will be registered 
    for name, wallet in [('foo.test', wallets[3]), ('bar.test', wallets[4]), ('baz.test', wallets[5])]:

        name_rec = state_engine.get_name( name )
        if name_rec is not None:
            print "Registered name record for %s" % name
            return False 

    # the single preordered name will be registered 
    name_rec = state_engine.get_name( 'goo.test' )
    if name_rec is None:
        print "No name record for %s" % name 
        return False 

    if name_rec['address'] != wallet[3].addr:
        print "'%s' not owned by '%s'" % (name, wallet.addr)
        return False 

    if name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallet[3].addr):
        print "'%s' not controlled by '%s'" % (name, pybitcoin.make_pay_to_address_script(wallet[3].addr))
        return False

    return True
def check( state_engine ):

    global reveal_blocks

    # the namespace should not exist
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        print "still revealed"
        return False 
    
    # should not be preordered
    namespace_preorder_hashes = state_engine.get_all_preordered_namespace_hashes()
    if len(namespace_preorder_hashes) != 0:
        print "preorder hashes: %s" % namespace_preorder_hashes
        return False 

    # examine historical form 
    for count in xrange(0, 3):
        ns = state_engine.get_namespace_at( "test", reveal_blocks[count] )
        if ns is None or len(ns) == 0:
            print "no namespace state at %s" % (reveal_blocks[count])
            return False

        ns = ns[0]

        # fields should match 
        for f in ['lifetime', 'coeff', 'base', 'nonalpha_discount', 'no_vowel_discount']:
            if ns[f] != count + 1:
                print "%s: expected %s, got %s" % (f, count+1, ns[f])
                return False

        buckets = [count] * 16
        if ns['buckets'] != buckets:
            print "buckets: expected %s, got %s" % ([count+1]*16, ns['buckets'])
            return False
        
        # reveal block should match 
        if ns['reveal_block'] != reveal_blocks[count]:
            print "reveal block: expected %s, got %s" % (reveal_blocks[count], ns['reveal_block'])
            return False

        # sender should match
        if ns['address'] != wallets[count].addr or ns['sender'] != pybitcoin.make_pay_to_address_script(wallets[count].addr):
            print "sender: expected %s, got %s" % (ns['address'], wallets[count].addr)
            return False

        # recipient should match 
        if ns['recipient_address'] != wallets[count+1].addr or ns['recipient'] != pybitcoin.make_pay_to_address_script(wallets[count+1].addr):
            print "recipient: expected %s, got %s" % (ns['recipient_address'], wallets[count+1].addr)
            return False


    return True
Example #29
0
def check( state_engine ):

    global wallets

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        return False 

    if ns['namespace_id'] != 'test':
        return False 

    # not preordered
    preorder = state_engine.get_name_preorder( "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr), wallets[3].addr )
    if preorder is not None:
        return False
    
    # registered 
    name_rec = state_engine.get_name( "foo.test" )
    if name_rec is None:
        return False 

    # updated, but revoked, so data should be None
    if name_rec['value_hash'] is not None:
        return False 

    # transferred 
    if name_rec['address'] != wallets[4].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallets[4].addr):
        return False 

    # previously owned by...
    name_rec_prev = state_engine.get_name_at( "foo.test", sorted( name_rec['history'].keys() )[-1] - 2 )[0]
    if name_rec_prev['address'] != wallets[3].addr or name_rec_prev['sender'] != pybitcoin.make_pay_to_address_script(wallets[3].addr):
        return False

    # revoked 
    if not name_rec['revoked']:
        return False 

    # verify that the user wallets (3 and 4) were *not* debited any btc
    rc = True
    for wallet in [wallets[3], wallets[4]]:
        unspents = testlib.get_unspents( wallet.addr )
        value = sum( [us['value'] for us in unspents] )
        if value < 100000000000:
            print "value of '%s' is '%s'" % (wallet.addr, value)
            rc = False

    return rc
def check( state_engine ):

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        return False 

    if ns['namespace_id'] != 'test':
        return False 

    names = ['foo.test', 'bar.test', 'baz.test']
    name_preorder_wallets = [wallets[2], wallets[3], wallets[4]]
    name_register_wallets = [wallets[5], wallets[6], wallets[7]]
    name_transfer_wallets = [wallets[6], wallets[7], wallets[5]]

    for i in xrange(0, len(names)):

        name = names[i]
        name_preorder_wallet = name_preorder_wallets[i]
        name_register_wallet = name_register_wallets[i]
        name_transfer_wallet = name_transfer_wallets[i]

        # not preordered
        preorder = state_engine.get_name_preorder( name, pybitcoin.make_pay_to_address_script(name_preorder_wallet.addr), name_register_wallet.addr )
        if preorder is not None:
            return False
        
        # registered 
        name_rec = state_engine.get_name( name )
        if name_rec is None:
            return False 

        # data is gone
        if name_rec['value_hash'] is not None:
            return False 

        # owned by the right transfer wallet 
        if name_rec['address'] != name_transfer_wallet.addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script(name_transfer_wallet.addr):
            return False

        # renewed 
        if name_rec['last_renewed'] == name_rec['first_registered']:
            return False 

        # revoked 
        if not name_rec['revoked']:
            return False 

    return True
Example #31
0
def check( state_engine ):

    global wallet_keys, datasets, zonefile_hash

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        print "namespace not ready"
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        print "no namespace"
        return False 

    if ns['namespace_id'] != 'test':
        print "wrong namespace"
        return False 

    # not preordered
    preorder = state_engine.get_name_preorder( "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr), wallets[3].addr )
    if preorder is not None:
        print "still have preorder"
        return False
    
    # registered 
    name_rec = state_engine.get_name( "foo.test" )
    if name_rec is None:
        print "name does not exist"
        return False 

    # owned 
    if name_rec['address'] != wallets[3].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallets[3].addr):
        print "name has wrong owner"
        return False 

    # have right hash 
    if name_rec['value_hash'] != zonefile_hash:
        print "Invalid zonefile hash"
        return False 

    # zonefile is NOT legacy 
    user_zonefile = blockstack_client.zonefile.load_name_zonefile( 'foo.test', zonefile_hash )
    if 'error' in user_zonefile:
        print json.dumps(user_zonefile, indent=4, sort_keys=True)
        return False 

    if blockstack_profiles.is_profile_in_legacy_format( user_zonefile ):
        print "legacy still"
        print json.dumps(user_zonefile, indent=4, sort_keys=True)
        return False
    
    res = testlib.blockstack_cli_lookup("foo.test")
    if 'error' in res:
        print 'error looking up profile: {}'.format(res)
        return False

    assert 'profile' in res
    assert 'zonefile' in res

    return True
def check( state_engine ):

    global wallet_keys, error, index_file_data, resource_data

    if error:
        print "Key operation failed."
        return False

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        print "namespace not ready"
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        print "no namespace"
        return False 

    if ns['namespace_id'] != 'test':
        print "wrong namespace"
        return False 

    names = ['foo.test']
    wallet_keys_list = [wallet_keys]
    test_proxy = testlib.TestAPIProxy()

    for i in xrange(0, len(names)):
        name = names[i]
        wallet_payer = 3 * (i+1) - 1
        wallet_owner = 3 * (i+1)
        wallet_data_pubkey = 3 * (i+1) + 1
        wallet_keys = wallet_keys_list[i]

        # not preordered
        preorder = state_engine.get_name_preorder( name, pybitcoin.make_pay_to_address_script(wallets[wallet_payer].addr), wallets[wallet_owner].addr )
        if preorder is not None:
            print "still have preorder"
            return False
    
        # registered 
        name_rec = state_engine.get_name( name )
        if name_rec is None:
            print "name does not exist"
            return False 

        # owned 
        if name_rec['address'] != wallets[wallet_owner].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallets[wallet_owner].addr):
            print "name has wrong owner"
            return False 

        # get app config 
        app_config = testlib.blockstack_cli_app_get_config( "foo.test", "ping.app" )
        if 'error' in app_config:
            print "failed to get app config\n{}\n".format(json.dumps(app_config, indent=4, sort_keys=True))
            return False

        # inspect...
        app_config = app_config['config']

        if app_config['driver_hints'] != []:
            print "Invalid driver hints\n{}\n".format(json.dumps(app_config, indent=4, sort_keys=True))
            return False

        if app_config['api_methods'] != ['node_read']:
            print "Invalid API list\n{}\n".format(json.dumps(app_config, indent=4, sort_keys=True))
            return False

        if len(app_config['index_uris']) != 1:
            print "Invalid URI records\n{}\n".format(json.dumps(app_config, indent=4, sort_keys=True))
            return False

        if app_config['blockchain_id'] != 'foo.test':
            print "invalid blockchain ID\n{}\n".format(app_config)
            return False

        # get index file 
        index_file = testlib.blockstack_cli_app_get_resource("foo.test", "ping.app", "index.html")
        if 'error' in index_file:
            print "failed to get index file\n{}\n".format(json.dumps(index_file, indent=4, sort_keys=True))
            return False
        
        if index_file['res'] != index_file_data:
            print "got wrong index file:\n{}\n".format(index_file['index_file'])
            return False

        # get resource 
        resource_data_res = testlib.blockstack_cli_app_get_resource("foo.test", "ping.app", "hello_world")
        if 'error' in resource_data_res:
            print "failed to get resource hello_world\n{}\n".format(json.dumps(resource_data, indent=4, sort_keys=True))
            return False

        if resource_data_res['res'] != resource_data:
            print "got wrong resource data:\n{}\nexpected:\n{}\n".format(resource_data_res['res'], resource_data)
            return False

    return True
Example #33
0
    def __init__(self, tx_path=None, tx_list=None, tx_grouping=1, start_block=0, start_time=0x11111111, difficulty=1.0, initial_utxos={}, **kw ):
        """
        Create a mock bitcoind connection, either from a 
        list of serialized transactions on-file, or a given Python
        list of serialized transactions.

        Transactions will be bundled into blocks in groups of size tx_grouping.
        """

        self.block_hashes = {}    # map block ID to block hash 
        self.blocks = {}        # map block hash to block info (including transaction IDs)
        self.txs = {}       # map tx hash to a list of transactions
        self.next_block_txs = []    # next block's transactions

        self.difficulty = difficulty 
        self.time = start_time 
        self.start_block = start_block 
        self.end_block = start_block
        
        self.block_hashes[ start_block - 1 ] = '00' * 32
        self.blocks[ '00' * 32 ] = {}
        
        # the initial utxos might be a serialized CSV (i.e. loaded directly from the config file).
        # if so, then parse it 
        if type(initial_utxos) in [str, unicode]:
            tmp = {}
            parts = initial_utxos.split(",")
            for utxo in parts:
                privkey, value = utxo.split(':')
                tmp[ privkey ] = int(value)

            initial_utxos = tmp
            
        tx_recs = []
        if tx_path is not None:
            with open( tx_path, "r" ) as f:
                tmp = f.readlines()
                tx_recs = [l.strip() for l in tmp]

        elif tx_list is not None:
            tx_recs = tx_list 

        # prepend utxos
        if len(initial_utxos) > 0:
            initial_outputs = []
            for (privkey, value) in initial_utxos.items():
                
                addr = pybitcoin.BitcoinPrivateKey( privkey ).public_key().address()
                out = {
                    'value': value,
                    'script_hex': pybitcoin.make_pay_to_address_script( addr )
                }
                initial_outputs.append( out )

            tx = {
                'inputs': [],
                'outputs': initial_outputs,
                'locktime': 0,
                'version': 0xff
            }
            
            tx_hex = tx_serialize( tx['inputs'], tx['outputs'], tx['locktime'], tx['version'] )
            tx_recs = [tx_hex] + tx_recs
       
        i = 0 
        while True:
            
            txs = []
            count = 0
            while i < len(tx_recs) and count < tx_grouping:
                txs.append( tx_recs[i] )
                i += 1

            if len(txs) > 0:
                for tx in txs:
                    self.sendrawtransaction( tx )
                self.flush_transactions()
            
            if i >= len(tx_recs):
                break
Example #34
0
def check( state_engine ):

    all_tests = {}

    # namespace preorder wire format
    # 0     2   3                                      23               39
    # |-----|---|--------------------------------------|----------------|
    #  magic op  hash(ns_id,script_pubkey,reveal_addr)   consensus hash  

    namespace_preorders = {
        "valid":     "%s%s" % ("11" * 20, "22" * 16),
        "too_short": "%s%s" % ("11" * 20, "33" * 15),
        "too_long":  "%s%s00" % ("11" * 20, "22" * 16),
    }

    all_tests["*"] = compile_test( "*", namespace_preorders )

    # namespace reveal wire format
    # 0     2   3        7     8     9    10   11   12   13   14    15    16    17       18        20                        39
    # |-----|---|--------|-----|-----|----|----|----|----|----|-----|-----|-----|--------|----------|-------------------------|
    # magic  op  life    coeff. base 1-2  3-4  5-6  7-8  9-10 11-12 13-14 15-16  nonalpha  version   namespace ID
    #                                                   bucket exponents         no-vowel
    #                                                                            discounts
   
    namespace_reveals = {
        "valid":      "%s%s%s%s%s%s%s%s%s%s%s%s%s%s" % ("11111111", "02", "03", "40", "41", "42", "43", "44", "45", "46", "47", "15", "6666", binascii.hexlify("hello")),
        "non-b38":    "%s%s%s%s%s%s%s%s%s%s%s%s%s%s" % ("11111111", "02", "03", "40", "41", "42", "43", "44", "45", "46", "47", "15", "6666", binascii.hexlify("Hello")),
        "period2":    "%s%s%s%s%s%s%s%s%s%s%s%s%s%s" % ("11111111", "02", "03", "40", "41", "42", "43", "44", "45", "46", "47", "15", "6666", binascii.hexlify("He.l.lo")),
        "period":     "%s%s%s%s%s%s%s%s%s%s%s%s%s%s" % ("11111111", "02", "03", "40", "41", "42", "43", "44", "45", "46", "47", "15", "6666", binascii.hexlify(".")),
        "no-plus":    "%s%s%s%s%s%s%s%s%s%s%s%s%s%s" % ("11111111", "02", "03", "40", "41", "42", "43", "44", "45", "46", "47", "15", "6666", binascii.hexlify("hel+lo")),
        "null_name":  "%s%s%s%s%s%s%s%s%s%s%s%s%s%s" % ("11111111", "02", "03", "40", "41", "42", "43", "44", "45", "46", "47", "15", "6666", binascii.hexlify("")),
        "too_long":   "%s%s%s%s%s%s%s%s%s%s%s%s%s%s" % ("11111111", "02", "03", "40", "41", "42", "43", "44", "45", "46", "47", "15", "6666", binascii.hexlify("hellohellohellohello"))
    }

    all_tests["&"] = compile_test( "&", namespace_reveals )

    # namespace ready wire format 
    # 0     2  3  4           23
    # |-----|--|--|------------|
    # magic op  .  ns_id

    namespace_readys = {
        "valid":     binascii.hexlify(".hello"),
        "non-b38":   binascii.hexlify(".Hello"),
        "period":    binascii.hexlify("."),
        "period2":   binascii.hexlify(".hel.lo"),
        "no-plus":   binascii.hexlify(".hel+lo"),
        "null_name": binascii.hexlify(""),
        "no-period": binascii.hexlify("hello"),
        "too_long":  binascii.hexlify(".hellohellohellohello")
    }

    all_tests["!"] = compile_test( "!", namespace_readys )

    # name preorder wire format
    # 0     2  3                                              23             39
    # |-----|--|----------------------------------------------|--------------|
    # magic op  hash(name.ns_id,script_pubkey,register_addr)   consensus hash

    name_preorders = {
        "valid":     "%s%s" % ("11" * 20, "22" * 16),
        "too_short": "%s%s" % ("11" * 20, "33" * 15),
        "too_long":  "%s%s00" % ("11" * 20, "22" * 16),
    }

    all_tests["?"] = compile_test( "?", name_preorders )

    # name register/renew wire format 
    # 0    2  3                             39
    # |----|--|-----------------------------|
    # magic op   name.ns_id (37 bytes)
    
    name_registrations = {
        "valid":     binascii.hexlify("hello.test"),
        "null_name": binascii.hexlify(""),
        "non-b38":   binascii.hexlify("Hello.test"),
        "no-namespace": binascii.hexlify("hello"),
        "null-namespace": binascii.hexlify("hello."),
        "2period":   binascii.hexlify("hello.tes.t"),
        "no-plus":   binascii.hexlify("hel+lo.test"),
        "too-long":  binascii.hexlify("hellohellohellohellohellohellohel.test")
    }

    all_tests[":"] = compile_test( ":", name_registrations )

    # name update wire format
    #  0     2  3                                   19                      39
    # |-----|--|-----------------------------------|-----------------------|
    # magic op  hash128(name.ns_id,consensus hash) hash160(data)
        
    name_updates = {
        "valid":        "%s%s" % ("11" * 16, "22" * 20),
        "too_short":    "%s%s" % ("11" * 16, "33" * 19),
        "too_long":     "%s%s00" % ("11" * 16, "22" * 20),
    }

    all_tests["+"] = compile_test( "+", name_updates )

    # name transfer wire format 
    # 0     2  3    4                   20              36
    # |-----|--|----|-------------------|---------------|
    # magic op keep  hash128(name.ns_id) consensus hash
    #          data?

    name_transfers = {
        "valid":        "%s%s%s" % (binascii.hexlify(">"), "11" * 16, "22" * 16),
        "valid2":        "%s%s%s" % (binascii.hexlify("~"), "11" * 16, "22" * 16),
        "too_short":    "%s%s%s" % (binascii.hexlify(">"), "11" * 16, "33" * 15),
        "too_long":     "%s%s%s00" % (binascii.hexlify(">"), "11" * 16, "22" * 16),
        "too_short2":    "%s%s%s" % (binascii.hexlify("~"), "11" * 16, "33" * 15),
        "too_long2":     "%s%s%s00" % (binascii.hexlify("~"), "11" * 16, "22" * 16),
        "invalid-opcode": "%s%s%s" % (binascii.hexlify("!"), "11" * 16, "22" * 16)
    }

    all_tests[">"] = compile_test( ">", name_transfers )

    # name revoke wire format
    # 0    2  3                             39
    # |----|--|-----------------------------|
    # magic op   name.ns_id (37 bytes)
    
    name_revokes = {
        "valid":     binascii.hexlify("hello.test"),
        "null_name": binascii.hexlify(""),
        "non-b38":   binascii.hexlify("Hello.test"),
        "no-namespace": binascii.hexlify("hello"),
        "null-namespace": binascii.hexlify("hello."),
        "2period":   binascii.hexlify("hello.tes.t"),
        "no-plus":   binascii.hexlify("hel+lo.test"),
        "too-long":  binascii.hexlify("hellohellohellohellohellohellohel.test")
    }

    all_tests["~"] = compile_test( "~", name_revokes )

    # name import wire format
    # 0    2  3                             39
    # |----|--|-----------------------------|
    # magic op   name.ns_id (37 bytes)
    
    name_imports = {
        "valid":     binascii.hexlify("hello.test"),
        "null_name": binascii.hexlify(""),
        "non-b38":   binascii.hexlify("Hello.test"),
        "no-namespace": binascii.hexlify("hello"),
        "null-namespace": binascii.hexlify("hello."),
        "2period":   binascii.hexlify("hello.tes.t"),
        "no-plus":   binascii.hexlify("hel+lo.test"),
        "too-long":  binascii.hexlify("hellohellohellohellohellohellohel.test")
    }
    
    all_tests[";"] = compile_test( ";", name_imports )

    # announce wire format 
    # 0    2  3                             23
    # |----|--|-----------------------------|
    # magic op   message hash (160-bit)
    
    announces = {
        "valid":    "11" * 20,
        "too-short": "11" * 19,
        "too-long": "11" * 21
    }

    all_tests["#"] = compile_test( "#", announces )

    fake_pubkey = wallets[0].pubkey_hex
    fake_sender = pybitcoin.make_pay_to_address_script( wallets[0].addr )
    fake_recipient = pybitcoin.make_pay_to_address_script( wallets[1].addr )
    fake_recipient_address = wallets[1].addr
    fake_import_update_hash = "44" * 20

    # only 'valid' tests should return non-NULL
    # all other tests should return None
    for opcode, tests in all_tests.items():
        print "test %s" % opcode
        for testname, testscript in tests.items():

            parsed_op = parse_nameop( opcode, testscript[3:], fake_pubkey, \
                    recipient=fake_recipient, recipient_address=fake_recipient_address, import_update_hash=fake_import_update_hash )

            if testname.startswith("valid"):
                # should work
                if parsed_op is None:
                    print >> sys.stderr, "Failed to parse valid id%s%s" % (opcode, testscript[3:])
                    return False 

            else:
                # should fail
                if parsed_op is not None:
                    print >> sys.stderr, "Parsed invalid test '%s' (id%s%s)" % (testname, opcode, testscript[3:])
                    return False

    return True
def check(state_engine):

    global last_first_block, first_preorder

    original_price = 6400000
    curr_price = original_price * blockstack_server.lib.config.get_epoch_price_multiplier(
        267, "test")

    # not revealed, but ready
    ns = state_engine.get_namespace_reveal("test")
    if ns is not None:
        return False

    ns = state_engine.get_namespace("test")
    if ns is None:
        return False

    if ns['namespace_id'] != 'test':
        return False

    # not preordered
    preorder = state_engine.get_name_preorder(
        "foo.test",
        pybitcoin.make_pay_to_address_script(wallets[2].addr),
        wallets[3].addr,
        include_failed=True)
    if preorder is not None:
        return False

    # registered
    name_rec = state_engine.get_name("foo.test")
    if name_rec is None:
        print "still expired"
        return False

    # blocks updated
    if name_rec['address'] != wallets[3].addr or name_rec[
            'sender'] != pybitcoin.make_pay_to_address_script(wallets[3].addr):
        print json.dumps(name_rec, indent=4, sort_keys=True)
        return False

    # check blocks
    if name_rec['first_registered'] != last_first_block:
        print "wrong first_registered; expected %s" % last_first_block
        print json.dumps(name_rec, indent=4, sort_keys=True)
        return False

    if name_rec['block_number'] != first_preorder:
        print "wrong block_number; expected %s" % last_first_preorder
        print json.dumps(name_rec, indent=4, sort_keys=True)
        return False

    # epoch 2 fee paid on second preorder
    if abs(name_rec['op_fee'] - curr_price) >= 10e-8:
        print "wrong fee: %s != %s" % (name_rec['op_fee'], curr_price)
        return False

    historic_name_rec = state_engine.get_name_at("foo.test",
                                                 first_preorder + 1,
                                                 include_expired=True)
    if historic_name_rec is None or len(historic_name_rec) == 0:
        print "no name at %s" % import_block_1
        return False

    # epoch 1 fee paid on first preorder
    historic_name_rec = historic_name_rec[0]
    if historic_name_rec['address'] != wallets[3].addr or historic_name_rec[
            'sender'] != pybitcoin.make_pay_to_address_script(wallets[3].addr):
        print "historic sender is wrong"
        return False

    if abs(historic_name_rec['op_fee'] - original_price) >= 10e-8:
        print "wrong historic fee at epoch 1: %s != %s" % (
            historic_name_rec['op_fee'], original_price)
        return False

    # epoch 2 fee paid on second preorder
    historic_name_rec = state_engine.get_name_at("foo.test",
                                                 last_first_block,
                                                 include_expired=True)
    if historic_name_rec is None or len(historic_name_rec) == 0:
        print "no name at %s" % import_block_1
        return False

    historic_name_rec = historic_name_rec[0]
    if abs(historic_name_rec['op_fee'] - curr_price) >= 10e-8:
        print "wrong historic fee at epoch 1: %s != %s" % (
            historic_name_rec['op_fee'], original_price)
        return False

    return True
Example #36
0
def check( state_engine ):

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is None:
        print "not revealed"
        return False 

    if ns['namespace_id'] != 'test':
        print "wrong namespace"
        return False 

    # not preordered 
    for i in xrange(0, len(wallets)):
        preorder = state_engine.get_name_preorder( "foo.test", pybitcoin.make_pay_to_address_script(wallets[i].addr), wallets[(i+1)%5].addr )
        if preorder is not None:
            print "preordered"
            return False

    # registered 
    name_rec = state_engine.get_name( "foo.test" )
    if name_rec is None:
        print "no name"
        return False 

    # updated, and data preserved
    if name_rec['value_hash'] != "66" * 20:
        print "wrong value hash"
        return False 

    # transferred 
    if name_rec['address'] != wallets[5].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script( wallets[5].addr ):
        print "wrong owner"
        return False

    # not preordered 
    for i in xrange(0, len(wallets)):
        preorder = state_engine.get_name_preorder( "bar.test", pybitcoin.make_pay_to_address_script(wallets[i].addr), wallets[(i+1)%5].addr )
        if preorder is not None:
            print "preordered"
            return False

    # registered 
    name_rec = state_engine.get_name( "bar.test" )
    if name_rec is None:
        print "no name"
        return False 

    # updated, and data preserved
    if name_rec['value_hash'] != "77" * 20:
        print "wrong value hash"
        return False 

    # transferred 
    if name_rec['address'] != wallets[3].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script( wallets[3].addr ):
        print "wrong owner"
        return False

    # not preordered 
    for i in xrange(0, len(wallets)):
        preorder = state_engine.get_name_preorder( "baz.test", pybitcoin.make_pay_to_address_script(wallets[i].addr), wallets[(i+1)%5].addr )
        if preorder is not None:
            print "preordered"
            return False

    # registered 
    name_rec = state_engine.get_name( "baz.test" )
    if name_rec is None:
        print "no name"
        return False 

    # updated, and data preserved
    if name_rec['value_hash'] != "88" * 20:
        print "wrong value hash"
        return False 

    # transferred 
    if name_rec['address'] != wallets[4].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script( wallets[4].addr ):
        print "wrong owner"
        return False

    return True
Example #37
0
def check(state_engine):

    global preorder_consensus

    # not revealed, but ready
    ns = state_engine.get_namespace_reveal("test")
    if ns is not None:
        return False

    ns = state_engine.get_namespace("test")
    if ns is None:
        return False

    if ns['namespace_id'] != 'test':
        return False

    # there won't be a preorder for an individual name...
    preorder = state_engine.get_name_preorder(
        "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr),
        wallets[3].addr)
    if preorder is not None:
        print "found name preorder for 'foo.test'"
        return False

    # there won't be a preorder for all names either
    preorder = state_engine.get_name_multi_preorder( ['foo.test', 'bar.test', 'baz.test'], \
                                                     pybitcoin.make_pay_to_address_script(wallets[2].addr), \
                                                     [wallets[3].addr, wallets[4].addr, wallets[5].addr])

    if preorder is not None:
        print "Preorder found for foo.test, bar.test, baz.test"
        return False

    prev_name_rec = None
    # each name will be registered
    for name, wallet in [('foo.test', wallets[3]), ('bar.test', wallets[4]),
                         ('baz.test', wallets[5])]:

        name_rec = state_engine.get_name(name)
        if name_rec is None:
            print "No name record for %s" % name
            return False

        if name_rec['address'] != wallet.addr:
            print "'%s' not owned by '%s'" % (name, wallet.addr)
            return False

        if name_rec['sender'] != pybitcoin.make_pay_to_address_script(
                wallet.addr):
            print "'%s' not controlled by '%s'" % (
                name, pybitcoin.make_pay_to_address_script(wallet.addr))
            return False

        if prev_name_rec is not None and prev_name_rec['history'] != name_rec[
                'history']:
            print "'%s' does not have the same preorder as '%s'" % (
                prev_name_rec['name'], name_rec['name'])
            return False

        prev_name_rec = name_rec

        return True
def check(state_engine):

    # not revealed, but ready
    ns = state_engine.get_namespace_reveal("test")
    if ns is not None:
        return False

    ns = state_engine.get_namespace("test")
    if ns is None:
        return False

    if ns['namespace_id'] != 'test':
        return False

    # name recs
    names = {
        "utr.test": {
            "address": wallets[1].addr,
            "value_hash": "00" * 20
        },
        "urt.test": {
            "address": wallets[3].addr,
            "value_hash": "00" * 20
        },
        "tur.test": {
            "address": wallets[5].addr,
            "value_hash": "11" * 20
        },
        "tru.test": {
            "address": wallets[7].addr,
            "value_hash": "22" * 20
        },
        "rut.test": {
            "address": wallets[9].addr,
            "value_hash": "11" * 20
        },
        "rtu.test": {
            "address": wallets[11].addr,
            "value_hash": "22" * 20
        }
    }

    for name in names.keys():
        name_rec = state_engine.get_name(name)
        if name_rec is None:
            print "missing %s" % name
            return False

        # check update
        if name_rec['value_hash'] != names[name]['value_hash']:
            print "value hash mismatch on %s: expected %s, got %s" % (
                name, names[name]['value_hash'], name_rec['value_hash'])
            return False

        # check owner
        if name_rec['address'] != names[name]['address'] or name_rec[
                'sender'] != pybitcoin.make_pay_to_address_script(
                    names[name]['address']):
            print "owner mismatch on %s: expected %s, got %s" % (
                name, names[name]['address'], name_rec['address'])
            return False

    return True
Example #39
0
def check(state_engine):

    global wallet_keys, datasets, zonefile_hash

    # not revealed, but ready
    ns = state_engine.get_namespace_reveal("test")
    if ns is not None:
        print "namespace not ready"
        return False

    ns = state_engine.get_namespace("test")
    if ns is None:
        print "no namespace"
        return False

    if ns['namespace_id'] != 'test':
        print "wrong namespace"
        return False

    # not preordered
    preorder = state_engine.get_name_preorder(
        "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr),
        wallets[3].addr)
    if preorder is not None:
        print "still have preorder"
        return False

    # registered
    name_rec = state_engine.get_name("foo.test")
    if name_rec is None:
        print "name does not exist"
        return False

    # owned
    if name_rec['address'] != wallets[3].addr or name_rec[
            'sender'] != pybitcoin.make_pay_to_address_script(wallets[3].addr):
        print "name has wrong owner"
        return False

    # have right hash
    if name_rec['value_hash'] != zonefile_hash:
        print "Invalid zonefile hash"
        return False

    # zonefile is NOT legacy
    user_zonefile = blockstack_client.zonefile.load_name_zonefile(
        'foo.test', zonefile_hash)
    if 'error' in user_zonefile:
        print json.dumps(user_zonefile, indent=4, sort_keys=True)
        return False

    if blockstack_profiles.is_profile_in_legacy_format(user_zonefile):
        print "legacy still"
        print json.dumps(user_zonefile, indent=4, sort_keys=True)
        return False

    # zonefile has no key
    zonefile_key = blockstack_client.user.user_zonefile_data_pubkey(
        user_zonefile)
    if zonefile_key is not None:
        print 'still have zonefile key'
        print json.dumps(user_zonefile, indent=4, sort_keys=True)
        return False

    # have right data
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy(test_proxy)

    for i in xrange(0, len(datasets)):
        print "get hello_world_%s" % (i + 1)
        dat = testlib.blockstack_cli_get_mutable(
            "foo.test", "hello_world_{}".format(i + 1))
        if dat is None:
            print "No data '%s'" % ("hello_world_%s" % (i + 1))
            return False

        if 'error' in dat:
            print json.dumps(dat, indent=4, sort_keys=True)
            return False

        if json.loads(dat['data']) != datasets[i]:
            print "Mismatch %s: %s != %s" % (i, dat, datasets[i])
            return False

    res = testlib.blockstack_cli_lookup("foo.test")
    if 'error' in res:
        print 'error looking up profile: {}'.format(res)
        return False

    assert 'profile' in res
    assert 'zonefile' in res

    return True
Example #40
0
def check(state_engine):

    global reveal_blocks

    # the namespace should not exist
    ns = state_engine.get_namespace_reveal("test")
    if ns is not None:
        print "still revealed"
        return False

    # should not be preordered
    namespace_preorder_hashes = state_engine.get_all_preordered_namespace_hashes(
    )
    if len(namespace_preorder_hashes) != 0:
        print "preorder hashes: %s" % namespace_preorder_hashes
        return False

    # examine historical form
    for count in xrange(0, 3):
        ns = state_engine.get_namespace_at("test", reveal_blocks[count])
        if ns is None or len(ns) == 0:
            print "no namespace state at %s" % (reveal_blocks[count])
            return False

        ns = ns[0]

        # fields should match
        for f in [
                'lifetime', 'coeff', 'base', 'nonalpha_discount',
                'no_vowel_discount'
        ]:
            if ns[f] != count + 1:
                print "%s: expected %s, got %s" % (f, count + 1, ns[f])
                return False

        buckets = [count] * 16
        if ns['buckets'] != buckets:
            print "buckets: expected %s, got %s" % ([count + 1] * 16,
                                                    ns['buckets'])
            return False

        # reveal block should match
        if ns['reveal_block'] != reveal_blocks[count]:
            print "reveal block: expected %s, got %s" % (reveal_blocks[count],
                                                         ns['reveal_block'])
            return False

        # sender should match
        if ns['address'] != wallets[count].addr or ns[
                'sender'] != pybitcoin.make_pay_to_address_script(
                    wallets[count].addr):
            print "sender: expected %s, got %s" % (ns['address'],
                                                   wallets[count].addr)
            return False

        # recipient should match
        if ns['recipient_address'] != wallets[count + 1].addr or ns[
                'recipient'] != pybitcoin.make_pay_to_address_script(
                    wallets[count + 1].addr):
            print "recipient: expected %s, got %s" % (ns['recipient_address'],
                                                      wallets[count + 1].addr)
            return False

    return True
Example #41
0
def make_outputs(data,
                 inputs,
                 register_addr,
                 change_addr,
                 renewal_fee=None,
                 pay_fee=True,
                 format='bin'):
    """
    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
    """

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

    if pay_fee:

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

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

    else:

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

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

    outputs = [
        # main output
        {
            "script_hex": make_op_return_script(data, format=format),
            "value": 0
        },

        # register address
        {
            "script_hex": make_pay_to_address_script(register_addr),
            "value": dust_value
        },

        # change address
        {
            "script_hex": make_pay_to_address_script(change_addr),
            "value": calculate_change_amount(inputs, bill, dust_fee)
        },
    ]

    if renewal_fee is not None:
        outputs.append(

            # burn address (when renewing)
            {
                "script_hex":
                make_pay_to_address_script(BLOCKSTORE_BURN_ADDRESS),
                "value": op_fee
            })

    return outputs
def check(state_engine):

    global wallet_keys, wallet_keys_2, datasets, zonefile_hash, zonefile_hash_2

    # not revealed, but ready
    ns = state_engine.get_namespace_reveal("test")
    if ns is not None:
        print "namespace not ready"
        return False

    ns = state_engine.get_namespace("test")
    if ns is None:
        print "no namespace"
        return False

    if ns['namespace_id'] != 'test':
        print "wrong namespace"
        return False

    # not preordered
    names = ['foo.test', 'bar.test']
    wallet_keys_list = [wallet_keys, wallet_keys_2]
    zonefile_hashes = [zonefile_hash[:], zonefile_hash_2[:]]

    for i in xrange(0, len(names)):
        name = names[i]
        wallet_payer = 3 * (i + 1) - 1
        wallet_owner = 3 * (i + 1)
        wallet_data_pubkey = 3 * (i + 1)  # same as owner key
        wallet_keys = wallet_keys_list[i]
        zonefile_hash = zonefile_hashes[i]

        preorder = state_engine.get_name_preorder(
            name,
            pybitcoin.make_pay_to_address_script(wallets[wallet_payer].addr),
            wallets[wallet_owner].addr)
        if preorder is not None:
            print "still have preorder"
            return False

        # registered
        name_rec = state_engine.get_name(name)
        if name_rec is None:
            print "name does not exist"
            return False

        # owned
        if name_rec['address'] != wallets[wallet_owner].addr or name_rec[
                'sender'] != pybitcoin.make_pay_to_address_script(
                    wallets[wallet_owner].addr):
            print "name has wrong owner"
            return False

        # zonefile is NOT legacy
        user_zonefile = blockstack_client.zonefile.load_name_zonefile(
            name, zonefile_hash)
        if 'error' in user_zonefile:
            print json.dumps(user_zonefile, indent=4, sort_keys=True)
            return False

        if blockstack_profiles.is_profile_in_legacy_format(user_zonefile):
            print "legacy still"
            print json.dumps(user_zonefile, indent=4, sort_keys=True)
            return False

        # zonefile has no key
        zonefile_key = blockstack_client.user.user_zonefile_data_pubkey(
            user_zonefile)
        if zonefile_key is not None:
            print 'still have zonefile key'
            print json.dumps(user_zonefile, indent=4, sort_keys=True)
            return False

        # still have all the right info
        user_profile = blockstack_client.profile.get_profile(
            name, user_zonefile=user_zonefile)
        if user_profile is None or 'error' in user_profile:
            if user_profile is not None:
                print json.dumps(user_profile, indent=4, sort_keys=True)
            else:
                print "\n\nprofile is None\n\n"

            return False

    # can get mutable data with owner address
    res = testlib.blockstack_cli_get_mutable("bar.test", "hello_world_mutable")

    if 'error' in res:
        print json.dumps(res, indent=4, sort_keys=True)
        return False

    if json.loads(res['data']) != {'hello': 'world'}:
        print 'invalid data: {}'.format(res['data'])
        return False

    # can get mutable data with explicit public key
    res = testlib.blockstack_cli_get_mutable(
        "bar.test",
        "hello_world_mutable",
        public_key=keylib.ECPrivateKey(
            wallet_keys_2['data_privkey']).public_key().to_hex())
    print 'mutable: {}'.format(res)

    if 'error' in res:
        print json.dumps(res, indent=4, sort_keys=True)
        return False

    if json.loads(res['data']) != {'hello': 'world'}:
        print 'invalid data: {}'.format(res['data'])
        return False

    # can get immutable data by name
    res = testlib.blockstack_cli_get_immutable('foo.test',
                                               'hello_world_immutable')
    print 'immutable by name: {}'.format(res)

    if 'error' in res:
        return res

    if json.loads(res['data']) != {'hello': 'world_immutable'}:
        print 'invalid immutable data: {}'.format(res['data'])
        return False

    # can get immutable data by hash
    hsh = res['hash']
    res = testlib.blockstack_cli_get_immutable('foo.test', hsh)
    print 'immutable: {}'.format(res)

    if 'error' in res:
        return res

    if json.loads(res['data']) != {'hello': 'world_immutable'}:
        print 'invalid immutable data by hash: {}'.format(res['data'])
        return False

    return True
def check(state_engine):

    # not revealed, but ready
    ns = state_engine.get_namespace_reveal("test")
    if ns is not None:
        print "namespace reveal exists"
        return False

    ns = state_engine.get_namespace("test")
    if ns is None:
        print "no namespace"
        return False

    if ns['namespace_id'] != 'test':
        print "wrong namespace"
        return False

    # registered
    name_rec = state_engine.get_name("foo.test")
    if name_rec is None:
        print "name does not exist"
        return False

    # owned by the right address
    owner_address = wallets[3].addr
    if name_rec['address'] != owner_address or name_rec[
            'sender'] != pybitcoin.make_pay_to_address_script(owner_address):
        print "sender is wrong"
        return False

    # all queues are drained
    queue_info = testlib.blockstack_client_queue_state()
    if len(queue_info) > 0:
        print "Still in queue:\n%s" % json.dumps(
            queue_info, indent=4, sort_keys=True)
        return False

    # have an update hash
    if 'value_hash' not in name_rec or name_rec.get('value_hash',
                                                    None) is None:
        print "No value hash"
        return False

    # have a zonefile
    zonefile = testlib.blockstack_get_zonefile(name_rec['value_hash'])
    if zonefile is None or 'error' in zonefile:
        if zonefile is not None:
            print "zonefile lookup error: %s" % zonefile['error']
        else:
            print "no zonefile returned"
        return False

    # hashes to this zonefile
    if blockstack_client.hash_zonefile(zonefile) != name_rec['value_hash']:
        print "wrong zonefile: %s != %s" % (
            blockstack_client.hash_zonefile(zonefile), name_rec['value_hash'])
        return False

    # verify that the profile is there
    profile = testlib.blockstack_get_profile("foo.test")
    if profile is None or 'error' in profile:
        if profile is None:
            print "no profile returned"
        else:
            print "profile lookup error: %s" % profile['error']

        return False

    return True
Example #44
0
def check(state_engine):

    global wallet_keys, datasets, zonefile_hash

    # not revealed, but ready
    ns = state_engine.get_namespace_reveal("test")
    if ns is not None:
        print "namespace not ready"
        return False

    ns = state_engine.get_namespace("test")
    if ns is None:
        print "no namespace"
        return False

    if ns['namespace_id'] != 'test':
        print "wrong namespace"
        return False

    # not preordered
    preorder = state_engine.get_name_preorder(
        "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr),
        wallets[3].addr)
    if preorder is not None:
        print "still have preorder"
        return False

    # registered
    name_rec = state_engine.get_name("foo.test")
    if name_rec is None:
        print "name does not exist"
        return False

    # owned
    if name_rec['address'] != wallets[3].addr or name_rec[
            'sender'] != pybitcoin.make_pay_to_address_script(wallets[3].addr):
        print "name has wrong owner"
        return False

    # have right hash
    if name_rec['value_hash'] != zonefile_hash:
        print "Invalid zonefile hash"
        return False

    # have no data
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy(test_proxy)

    for i in xrange(0, len(datasets)):
        print "get hello_world_%s" % (i + 1)
        dat = blockstack_client.get_mutable("foo.test",
                                            "hello_world_%s" % (i + 1))
        if dat is not None and 'error' not in dat:
            print "still have '%s'\n%s" % (
                "hello_world_%s" %
                (i + 1), json.dumps(dat, indent=4, sort_keys=True))
            return False

        if 'error' in dat and dat['error'] != 'No such mutable datum':
            print json.dumps(dat, indent=4, sort_keys=True)
            return False

    return True
def check( state_engine ):

    global wallet_keys, wallet_keys_2, datasets, zonefile_hash, zonefile_hash_2

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        print "namespace not ready"
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        print "no namespace"
        return False 

    if ns['namespace_id'] != 'test':
        print "wrong namespace"
        return False 

    # not preordered
    names = ['foo.test', 'bar.test']
    wallet_keys_list = [wallet_keys, wallet_keys_2]
    zonefile_hashes = [zonefile_hash[:], zonefile_hash_2[:]]

    for i in xrange(0, len(names)):
        name = names[i]
        wallet_payer = 3 * (i+1) - 1
        wallet_owner = 3 * (i+1)
        wallet_data_pubkey = 3 * (i+1)  # same as owner key
        wallet_keys = wallet_keys_list[i]
        zonefile_hash = zonefile_hashes[i]

        preorder = state_engine.get_name_preorder( name, pybitcoin.make_pay_to_address_script(wallets[wallet_payer].addr), wallets[wallet_owner].addr )
        if preorder is not None:
            print "still have preorder"
            return False
    
        # registered 
        name_rec = state_engine.get_name( name )
        if name_rec is None:
            print "name does not exist"
            return False 

        # owned 
        if name_rec['address'] != wallets[wallet_owner].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallets[wallet_owner].addr):
            print "name has wrong owner"
            return False 

        # zonefile is NOT legacy 
        user_zonefile = blockstack_client.profile.load_name_zonefile( name, zonefile_hash )
        if 'error' in user_zonefile:
            print json.dumps(user_zonefile, indent=4, sort_keys=True)
            return False 

        if blockstack_profiles.is_profile_in_legacy_format( user_zonefile ):
            print "legacy still"
            print json.dumps(user_zonefile, indent=4, sort_keys=True)
            return False

        # still have all the right info 
        user_profile = blockstack_client.profile.load_name_profile( name, user_zonefile, wallets[wallet_data_pubkey].addr, wallets[wallet_owner].addr )
        if user_profile is None:
            print "Unable to load user profile for %s (%s)" % (name, wallets[wallet_data_pubkey].pubkey_hex)
            return False

        if 'error' in user_profile:
            print json.dumps(user_profile, indent=4, sort_keys=True)
            return False

    # can fetch latest by name 
    immutable_data = get_data( "blockstack://hello_world_immutable.foo.test/" )
    if 'error' in immutable_data:
        print json.dumps(immutable_data, indent=4, sort_keys=True)
        return False 

    if immutable_data['data'] != {'hello': 'world'}:
        print "immutable fetch-latest mismatch:\n%s (%s)\n%s" % (immutable_data['data'], type(immutable_data['data']), {'hello': 'world'})
        return False 

    if immutable_data['hash'] != immutable_hash:
        print "immutable fetch-latest hash mismatch: %s != %s" % (immutable_data['hash'], immutable_hash)
        return False 

    # can fetch by name and hash
    immutable_data = get_data( "blockstack://hello_world_immutable.foo.test/#%s" % immutable_hash )
    if 'error' in immutable_data:
        print json.dumps(immutable_data, indent=4, sort_keys=True)
        return False 

    if immutable_data['data'] != {'hello': 'world'}:
        print "immutable fetch-by-hash mismatch:\n%s (%s)\n%s" % (immutable_data['data'], type(immutable_data['data']), {'hello': 'world'})
        return False 

    if immutable_data['hash'] != immutable_hash:
        print "immutable fetch-by-hash mismatch: %s != %s" % (immutable_data['hash'], immutable_hash)
        return False 

    # hash must match (if we put the wrong hash, it must fail)
    try:
        immutable_data = get_data( "blockstack://hello_world_immutable.foo.test/#%s" % ("0" * len(immutable_hash)))
        print "no error"
        print json.dumps(immutable_data, indent=4, sort_keys=True)
        return False
    except urllib2.URLError:
        pass

    # can list names and hashes
    immutable_data_list = get_data( "blockstack://foo.test/#immutable" )
    if 'error' in immutable_data_list:
        print json.dumps(immutable_data, indent=4, sort_keys=True )
        return False 

    if len(immutable_data_list['data']) != 1:
        print "multiple immutable data"
        print json.dumps(immutable_data_list, indent=4, sort_keys=True )
        return False 

    if immutable_data_list['data'][0]['data_id'] != 'hello_world_immutable' or immutable_data_list['data'][0]['hash'] != immutable_hash:
        print "wrong data ID and/or hash"
        print json.dumps(immutable_data_list, indent=4, sort_keys=True )
        return False 

    # can fetch latest mutable by name
    mutable_data = get_data( "blockstack://bar.test/hello_world_mutable")
    if 'error' in mutable_data:
        print json.dumps(mutable_data, indent=4, sort_keys=True)
        return False 

    if mutable_data['data'] != {'hello': 'world'}:
        print json.dumps(mutable_data, indent=4, sort_keys=True)
        return False

    if mutable_data['version'] != 1:
        print "wrong version: %s" % mutable_data['data']['version']
        return False 

    # can fetch by version
    mutable_data = get_data( "blockstack://bar.test/hello_world_mutable#1")
    if 'error' in mutable_data:
        print json.dumps(mutable_data, indent=4, sort_keys=True)
        return False 

    if mutable_data['data'] != {'hello': 'world'}:
        print json.dumps(mutable_data, indent=4, sort_keys=True)
        return False 

    # will fail to fetch if we give the wrong version 
    try:
        mutable_data = get_data("blockstack://bar.test/hello_world_mutable#2")
        print "mutable fetch by wrong version worked"
        print json.dumps(mutable_data, indent=4, sort_keys=True)
        return False
    except urllib2.URLError:
        pass

    # can list mutable data
    mutable_data_list = get_data( "blockstack://bar.test/#mutable" )
    if 'error' in mutable_data_list:
        print json.dumps(mutable_data_list, indent=4, sort_keys=True )
        return False 

    if len(mutable_data_list) != 1:
        print "multiple mutable data"
        print json.dumps(mutable_data_list, indent=4, sort_keys=True )
        return False 

    if mutable_data_list['data'][0]['data_id'] != 'hello_world_mutable' or mutable_data_list['data'][0]['version'] != 1:
        print "wrong data id and/or version"
        print json.dumps(mutable_data_list, indent=4, sort_keys=True)
        return False

    return True
def check(state_engine):

    global snv_block_id_foo, snv_txid_bar, last_consensus

    # not revealed, but ready
    ns = state_engine.get_namespace_reveal("test")
    if ns is not None:
        return False

    ns = state_engine.get_namespace("test")
    if ns is None:
        return False

    if ns['namespace_id'] != 'test':
        return False

    # not preordered
    for i in xrange(0, len(wallets)):
        for name in ["foo.test", "bar.test", "baz.test"]:
            preorder = state_engine.get_name_preorder(
                name, pybitcoin.make_pay_to_address_script(wallets[i].addr),
                wallets[(i + 1) % 5].addr)
            if preorder is not None:
                print "preordered"
                return False

    # but still registered
    for name in ["foo.test", "bar.test", "baz.test"]:
        name_rec = state_engine.get_name(name)
        if name_rec is None:
            print "no name"
            return False

    # updated, and data preserved
    name_rec = state_engine.get_name("baz.test")
    if name_rec['value_hash'] != "22" * 20:
        print "wrong value hash"
        return False

    # transferred
    name_rec = state_engine.get_name("bar.test")
    if name_rec['address'] != wallets[4].addr or name_rec[
            'sender'] != pybitcoin.make_pay_to_address_script(wallets[4].addr):
        print "wrong owner"
        return False

    # snv lookup works
    # NOTE: cannot use serial numbers here, since a NAME_IMPORT does not contain a consensus hash.
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy(test_proxy)
    bitcoind = testlib.get_bitcoind()

    snv_rec = blockstack_client.snv_lookup("foo.test",
                                           snv_block_id_foo,
                                           last_consensus,
                                           proxy=test_proxy)
    if 'error' in snv_rec:
        print json.dumps(snv_rec, indent=4)
        print "failed to look up foo.test from consensus hash %s" % last_consensus
        return False

    # can use bar.test's NAME_TRANSFER txid to verify foo.test, since it has a consensus hash
    snv_rec_bar_tx = blockstack_client.snv_lookup("foo.test",
                                                  snv_block_id_foo,
                                                  snv_txid_bar,
                                                  proxy=test_proxy)
    if 'error' in snv_rec_bar_tx:
        print json.dumps(snv_rec_bar_tx, indent=4)
        print "failed to look up foo.test from transaction %s" % snv_txid_bar
        return False

    if snv_rec != snv_rec_bar_tx:
        print "--------"
        print json.dumps(snv_rec, indent=4)
        print ""
        print json.dumps(snv_rec_bar_tx, indent=4)
        print ""
        print "Not equal"
        return False

    print snv_rec

    return True
def check(state_engine):

    global update_blocks, transfer_blocks, update_hashes, transfer_recipients, renew_blocks

    # not revealed, but ready
    ns = state_engine.get_namespace_reveal("test")
    if ns is not None:
        return False

    ns = state_engine.get_namespace("test")
    if ns is None:
        return False

    if ns['namespace_id'] != 'test':
        return False

    # not preordered
    preorder = state_engine.get_name_preorder(
        "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr),
        wallets[3].addr)
    if preorder is not None:
        print json.dumps(name_rec, indent=4)
        return False

    # registered to new owner
    name_rec = state_engine.get_name("foo.test")
    if name_rec is None:
        print "name rec is None"
        return False

    # updated
    if name_rec['value_hash'] != '04' * 20:
        print "invalid value hash"
        return False

    # transferred
    if name_rec['address'] != wallets[4].addr or name_rec[
            'sender'] != pybitcoin.make_pay_to_address_script(wallets[4].addr):
        print json.dumps(name_rec, indent=4)
        return False

    # historically updated and transferred and renewed
    if len(transfer_blocks) != len(update_blocks):
        print "test bug: did not transfer or update the right amount of times"
        return False

    for i in xrange(0, len(transfer_blocks)):
        transfer_block = transfer_blocks[i]
        transfer_recipient = transfer_recipients[i]

        historic_name_rec = state_engine.get_name_at("foo.test",
                                                     transfer_block,
                                                     include_expired=True)
        if historic_name_rec is None or len(historic_name_rec) == 0:
            print "no name at %s" % transfer_block
            return False

        historic_name_rec = historic_name_rec[0]
        if historic_name_rec['opcode'] != 'NAME_TRANSFER':
            print "was not transfered at %s" % transfer_block
            return False

        if historic_name_rec[
                'address'] != transfer_recipient or historic_name_rec[
                    'sender'] != pybitcoin.make_pay_to_address_script(
                        transfer_recipient):
            print "wrong address/sender, got %s, %s" % (
                historic_name_rec['address'], historic_name_rec['sender'])
            return False

    for i in xrange(0, len(update_blocks)):
        update_block = update_blocks[i]
        update_hash = update_hashes[i]

        historic_name_rec = state_engine.get_name_at("foo.test",
                                                     update_block,
                                                     include_expired=True)
        if historic_name_rec is None or len(historic_name_rec) == 0:
            print "No name at %s" % update_block
            return False

        historic_name_rec = historic_name_rec[0]
        if historic_name_rec['opcode'] != 'NAME_UPDATE':
            print "was not updated at %s" % update_block
            return False

        if historic_name_rec.get('value_hash', None) != update_hash:
            print "wrong update hash: expected %s, got %s" % (
                update_hash, historic_name_rec.get('value_hash', None))
            return False

    for i in xrange(0, len(renew_blocks)):
        renew_block = renew_blocks[i]

        historic_name_rec = state_engine.get_name_at("foo.test",
                                                     renew_block,
                                                     include_expired=True)
        if historic_name_rec is None or len(historic_name_rec) == 0:
            print "name doesn't exist at %s" % renew_block
            return False

        historic_name_rec = historic_name_rec[0]
        if historic_name_rec['op'] != '::':
            print "name not renewed at %s" % renew_block
            return False

    return True
Example #48
0
def check( state_engine ):

    global wallet_keys, wallet_keys_2, key_names, error, gpghome

    if error:
        print "Key operation failed."
        return False

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        print "namespace not ready"
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        print "no namespace"
        return False 

    if ns['namespace_id'] != 'test':
        print "wrong namespace"
        return False 

    # not preordered
    names = ['foo.test', 'bar.test']
    wallet_keys_list = [wallet_keys, wallet_keys_2]

    for i in xrange(0, len(names)):
        name = names[i]
        wallet_payer = 3 * (i+1) - 1
        wallet_owner = 3 * (i+1)
        wallet_data_pubkey = 3 * (i+1) # same as owner key
        wallet_keys = wallet_keys_list[i]
        key_res = key_names[name]

        preorder = state_engine.get_name_preorder( name, pybitcoin.make_pay_to_address_script(wallets[wallet_payer].addr), wallets[wallet_owner].addr )
        if preorder is not None:
            print "still have preorder"
            return False
    
        # registered 
        name_rec = state_engine.get_name( name )
        if name_rec is None:
            print "name does not exist"
            return False 

        # owned 
        if name_rec['address'] != wallets[wallet_owner].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallets[wallet_owner].addr):
            print "name has wrong owner"
            return False 

        # account listing exists, and other keys are deleted
        account_key_listing = blockstack_gpg.gpg_list_profile_keys( name )
        secure_app_listing = blockstack_gpg.gpg_list_app_keys( name, "secure_messaging" )
        less_secure_app_listing = blockstack_gpg.gpg_list_app_keys( name, "less-secure_messaging" )

        if 'error' in account_key_listing:
            print json.dumps(account_key_listing)
            return False 

        if len(account_key_listing) != 1:
            print "Invalid account keys:\n%s" % json.dumps(account_key_listing)
            return False 

        key_id, key_url = account_key_listing[0]['identifier'], account_key_listing[0]['contentUrl']
        if key_url != key_res[0]['key_url']:
            print "Key ID mismatch (account): %s != %s\nFull listing:\n%s\n\nKeys we generated:\n%s\n" % \
                    (key_url, key_res[0]['key_url'], account_key_listing[0], json.dumps(key_res, indent=4, sort_keys=True))
            return False 

        # immutable listings exist, and other keys are deleted
        if 'error' in secure_app_listing:
            print json.dumps(secure_app_listing)
            return False 

        if len(secure_app_listing) != 1:
            print "Invalid immutable keys:\n%s" % json.dumps(secure_app_listing)
            return False 

        key_id, key_url = secure_app_listing[0]['keyName'], secure_app_listing[0]['contentUrl']
        if key_url != key_res[1]['key_url']:
            print "Key ID mismatch (immutable app): %s != %s\nFull listing:\n%s\n\nKeys we generated:\n%s\n" % \
                    (key_url, key_res[1]['key_url'], secure_app_listing[0], json.dumps(key_res, indent=4, sort_keys=True))
            return False 

        # mutable listings exist, and other keys are deleted
        if 'error' in less_secure_app_listing:
            print json.dumps(less_secure_app_listing)
            return False 

        if len(less_secure_app_listing) != 1:
            print "Invalid mutable keys (mutable app):\n%s" % json.dumps(less_secure_app_listing)
            return False 

        key_id, key_url = less_secure_app_listing[0]['keyName'], less_secure_app_listing[0]['contentUrl']
        if key_url != key_res[2]['key_url']:
            print "Key ID mismatch: %s != %s\nFull listing:\n%s\n\nKeys we generated:\n%s\n" % \
                    (key_url, key_res[2]['key_url'], less_secure_app_listing[0], json.dumps(key_res, indent=4, sort_keys=True))
            return False

        profile_key = blockstack_gpg.gpg_profile_get_key( name, account_key_listing[0]['keyName'], gpghome=gpghome )
        if 'error' in profile_key:
            print "no key in account %s: %s" % (account_key_listing, profile_key['error'])
            return False

        secure_app_key = blockstack_gpg.gpg_app_get_key( name, "secure_messaging", secure_app_listing[0]['keyName'], \
                                                         immutable=True )

        if 'error' in secure_app_key:
            print "no key in secure_messaging listing %s: %s" % (secure_app_listing, secure_app_key['error'])
            return False

        less_secure_app_key = blockstack_gpg.gpg_app_get_key( name, "less-secure_messaging", less_secure_app_listing[0]['keyName'] )
        if 'error' in less_secure_app_key:
            print "no key in less-secure_messaging listing %s: %s" % (less_secure_app_listing, less_secure_app_key['error'])
            return False

    return True
Example #49
0
def check(state_engine):

    global zonefile_hash

    # not revealed, but ready
    ns = state_engine.get_namespace_reveal("test")
    if ns is not None:
        print "namespace reveal exists"
        return False

    ns = state_engine.get_namespace("test")
    if ns is None:
        print "no namespace"
        return False

    if ns['namespace_id'] != 'test':
        print "wrong namespace"
        return False

    # registered
    name_rec = state_engine.get_name("foo.test")
    if name_rec is None:
        print "name does not exist"
        return False

    # owned by
    owner_address = wallets[4].addr
    if name_rec['address'] != owner_address or name_rec[
            'sender'] != pybitcoin.make_pay_to_address_script(owner_address):
        print "sender is wrong"
        return False

    # value hash
    if name_rec['value_hash'] != zonefile_hash:
        print "wrong zonefile hash: %s != %s" % (name_rec['value_hash'],
                                                 zonefile_hash)
        return False

    # replicated?
    zonefile = testlib.blockstack_get_zonefile(zonefile_hash)
    if 'error' in zonefile:
        print "zonefile error: %s" % zonefile['error']
        return False

    # right hash?
    if blockstack_client.hash_zonefile(zonefile) != zonefile_hash:
        print "wrong zonefile: %s != %s" % (
            blockstack_client.hash_zonefile(zonefile), zonefile_hash)
        return False

    # latest key?
    if not zonefile.has_key("txt"):
        print "no txt:\n%s" % json.dumps(zonefile, indent=4, sort_keys=True)
        return False

    if len(zonefile['txt']) != 2:
        print "wrong number of txt records:\n%s" % json.dumps(
            zonefile, indent=4, sort_keys=True)
        return False

    for txtrec in zonefile['txt']:
        if txtrec['name'] == 'pubkey':
            if new_data_pubkey not in txtrec['txt']:
                print "wrong pubkey:\n%s" % json.dumps(
                    zonefile, indent=4, sort_keys=True)
                print "missing %s" % new_data_pubkey
                return False

    names_owned = testlib.blockstack_cli_names()
    if 'error' in names_owned:
        print "rpc names: %s" % names_owned['error']
        return False

    # we still own the name
    if len(names_owned['names_owned']) != 1:
        print "owned: %s" % names_owned['names_owned']
        return False

    # all queues are drained
    queue_info = testlib.blockstack_client_queue_state()
    if len(queue_info) > 0:
        print "Still in queue:\n%s" % json.dumps(
            queue_info, indent=4, sort_keys=True)
        return False

    return True
def check(state_engine):

    global wallet_keys, wallet_keys_2, datasets, zonefile_hash, zonefile_hash_2, datastore_name

    # not revealed, but ready
    ns = state_engine.get_namespace_reveal("test")
    if ns is not None:
        print "namespace not ready"
        return False

    ns = state_engine.get_namespace("test")
    if ns is None:
        print "no namespace"
        return False

    if ns['namespace_id'] != 'test':
        print "wrong namespace"
        return False

    # not preordered
    names = ['foo.test', 'bar.test']
    wallet_keys_list = [wallet_keys, wallet_keys_2]
    zonefile_hashes = [zonefile_hash[:], zonefile_hash_2[:]]

    for i in xrange(0, len(names)):
        name = names[i]
        wallet_payer = 3 * (i + 1) - 1
        wallet_owner = 3 * (i + 1)
        wallet_data_pubkey = 3 * (i + 1) + 1
        wallet_keys = wallet_keys_list[i]
        zonefile_hash = zonefile_hashes[i]

        preorder = state_engine.get_name_preorder(
            name,
            pybitcoin.make_pay_to_address_script(wallets[wallet_payer].addr),
            wallets[wallet_owner].addr)
        if preorder is not None:
            print "still have preorder"
            return False

        # registered
        name_rec = state_engine.get_name(name)
        if name_rec is None:
            print "name does not exist"
            return False

        # owned
        if name_rec['address'] != wallets[wallet_owner].addr or name_rec[
                'sender'] != pybitcoin.make_pay_to_address_script(
                    wallets[wallet_owner].addr):
            print "name has wrong owner"
            return False

        # zonefile is NOT legacy
        user_zonefile = blockstack_client.load_name_zonefile(
            name, zonefile_hash)
        if 'error' in user_zonefile:
            print json.dumps(user_zonefile, indent=4, sort_keys=True)
            return False

        if blockstack_profiles.is_profile_in_legacy_format(user_zonefile):
            print "legacy still"
            print json.dumps(user_zonefile, indent=4, sort_keys=True)
            return False

        # still have all the right info
        user_profile = blockstack_client.get_profile(
            name, user_zonefile=user_zonefile)
        if user_profile is None:
            print "Unable to load user profile for %s (%s)" % (
                name, wallets[wallet_data_pubkey].pubkey_hex)
            return False

        if 'error' in user_profile:
            print json.dumps(user_profile, indent=4, sort_keys=True)
            return False

    # can fetch latest by name
    immutable_data = get_data("blockstack://hello_world_immutable.foo.test/")
    if 'error' in immutable_data:
        print json.dumps(immutable_data, indent=4, sort_keys=True)
        return False

    if json.loads(immutable_data['data']) != {'hello': 'world'}:
        print "immutable fetch-latest mismatch:\n%s (%s)\n%s" % (
            immutable_data['data'], type(immutable_data['data']), {
                'hello': 'world'
            })
        return False

    if immutable_data['hash'] != immutable_hash:
        print "immutable fetch-latest hash mismatch: %s != %s" % (
            immutable_data['hash'], immutable_hash)
        return False

    # can fetch by name and hash
    immutable_data = get_data(
        "blockstack://hello_world_immutable.foo.test/#%s" % immutable_hash)
    if 'error' in immutable_data:
        print json.dumps(immutable_data, indent=4, sort_keys=True)
        return False

    if json.loads(immutable_data['data']) != {'hello': 'world'}:
        print "immutable fetch-by-hash mismatch:\n%s (%s)\n%s" % (
            immutable_data['data'], type(immutable_data['data']), {
                'hello': 'world'
            })
        return False

    if immutable_data['hash'] != immutable_hash:
        print "immutable fetch-by-hash mismatch: %s != %s" % (
            immutable_data['hash'], immutable_hash)
        return False

    # hash must match (if we put the wrong hash, it must fail)
    try:
        immutable_data = get_data(
            "blockstack://hello_world_immutable.foo.test/#%s" %
            ("0" * len(immutable_hash)))
        print "no error"
        print json.dumps(immutable_data, indent=4, sort_keys=True)
        return False
    except urllib2.URLError:
        pass

    # can list names and hashes
    immutable_data_list = get_data("blockstack://foo.test/#immutable")
    if 'error' in immutable_data_list:
        print json.dumps(immutable_data, indent=4, sort_keys=True)
        return False

    if len(immutable_data_list['data']) != 2:
        print "multiple immutable data"
        print json.dumps(immutable_data_list, indent=4, sort_keys=True)
        return False

    # order preserved
    if immutable_data_list['data'][0][
            'data_id'] != 'hello_world_immutable' or immutable_data_list[
                'data'][0]['hash'] != immutable_hash:
        print "wrong data ID and/or hash"
        print json.dumps(immutable_data_list, indent=4, sort_keys=True)
        return False

    device_id = blockstack_client.config.get_local_device_id()
    data_id = blockstack_client.storage.make_fq_data_id(
        device_id, 'hello_world_mutable')

    # can fetch latest mutable by name
    mutable_data = get_data("blockstack://bar.test/{}".format(data_id))
    if 'error' in mutable_data:
        print json.dumps(mutable_data, indent=4, sort_keys=True)
        return False

    if json.loads(mutable_data['data']) != {'hello': 'world'}:
        print json.dumps(mutable_data, indent=4, sort_keys=True)
        return False

    if mutable_data['version'] != 1:
        print "wrong version: %s" % mutable_data['data']['version']
        return False

    # can fetch by version
    mutable_data = get_data("blockstack://bar.test/{}#1".format(data_id))
    if 'error' in mutable_data:
        print json.dumps(mutable_data, indent=4, sort_keys=True)
        return False

    if json.loads(mutable_data['data']) != {'hello': 'world'}:
        print json.dumps(mutable_data, indent=4, sort_keys=True)
        return False

    # will fail to fetch if we give the wrong version
    try:
        mutable_data = get_data("blockstack://bar.test/{}#2".format(data_id))
        print "mutable fetch by wrong version worked"
        print json.dumps(mutable_data, indent=4, sort_keys=True)
        return False
    except urllib2.URLError:
        pass

    # can fetch mutable data put by URL
    data_id = blockstack_client.storage.make_fq_data_id(device_id, 'foo_data2')
    mutable_data = get_data("blockstack://foo.test/{}".format(data_id))
    if 'error' in mutable_data or 'data' not in mutable_data or 'version' not in mutable_data:
        print json.dumps(mutable_data, indent=4, sort_keys=True)
        return False

    if json.loads(mutable_data['data']) != {'hello2': 'world2'}:
        print "Invalid mutable data fetched from blockstack://foo.test/{}".format(
            data_id)
        print json.dumps(mutable_data, indent=4, sort_keys=True)
        return False

    # can fetch immutable data put by URL
    immutable_data = get_data("blockstack://foo_immutable.foo.test")
    if 'error' in immutable_data or 'hash' not in immutable_data:
        print json.dumps(immutable_data, indent=4, sort_keys=True)
        return False

    if json.loads(immutable_data['data']) != {'hello3': 'world3'}:
        print "Invalid immutable data fetched from blockstack://foo_immutable.foo.test"
        print json.dumps(immutable_data, indent=4, sort_keys=True)
        return False

    # can fetch files and directories
    mutable_data = get_data(
        "blockstack://{}@foo-app.com/hello_datastore".format(datastore_name))
    if 'error' in mutable_data or 'file' not in mutable_data or mutable_data[
            'file']['idata'] != 'hello datastore':
        print 'Failed to get blockstack://{}@foo-app.com/hello_datastore'.format(
            datastore_name)
        print json.dumps(mutable_data, indent=4, sort_keys=True)
        return False

    mutable_data = get_data(
        "blockstack://{}@foo-app.com/hello_dir/".format(datastore_name))
    if 'error' in mutable_data or 'dir' not in mutable_data or 'hello_dir_datastore' not in mutable_data[
            'dir']['idata'].keys():
        print 'Failed to get blockstack://{}@foo-app.com/hello_dir/'.format(
            datastore_name)
        print json.dumps(mutable_data, indent=4, sort_keys=True)
        return False

    mutable_data = get_data(
        "blockstack://{}@foo-app.com/hello_dir/hello_dir_datastore".format(
            datastore_name))
    if 'error' in mutable_data or 'file' not in mutable_data or mutable_data[
            'file']['idata'] != 'hello dir datastore':
        print 'Failed to get blockstack://{}@foo-app.com/hello_dir/hello_dir_datastore'.format(
            datastore_name)
        print json.dumps(mutable_data, indent=4, sort_keys=True)
        return False

    return True
Example #51
0
def check(state_engine):

    global update_block

    # not revealed, but ready
    ns = state_engine.get_namespace_reveal("test")
    if ns is not None:
        return False

    ns = state_engine.get_namespace("test")
    if ns is None:
        return False

    if ns['namespace_id'] != 'test':
        return False

    # not preordered
    for i in xrange(0, len(wallets)):
        preorder = state_engine.get_name_preorder(
            "foo.test", pybitcoin.make_pay_to_address_script(wallets[i].addr),
            wallets[(i + 1) % 5].addr)
        if preorder is not None:
            print "preordered"
            return False

    # registered
    name_rec = state_engine.get_name("foo.test")
    if name_rec is None:
        print "no name"
        return False

    # no longer renewed
    if name_rec['last_renewed'] != name_rec['first_registered']:
        print name_rec['last_renewed']
        print name_rec['first_registered']
        return False

    # owned by
    if name_rec['address'] != wallets[8].addr or name_rec[
            'sender'] != pybitcoin.make_pay_to_address_script(wallets[8].addr):
        print "sender is wrong"
        return False

    # has new sender pubkey (from the payment key)
    if name_rec['sender_pubkey'] != wallets[7].pubkey_hex:
        print "wrong pubkey: %s != %s" % (name_rec['sender_pubkey'],
                                          wallets[7].pubkey_hex)
        return False

    # has no value hash
    if name_rec['value_hash'] is not None:
        print "still has value hash"
        return False

    # historically, name was updated
    historic_name_rec = state_engine.get_name_at("foo.test",
                                                 update_block,
                                                 include_expired=True)
    if historic_name_rec is None or len(historic_name_rec) == 0:
        print "no name at %s" % update_block
        return False

    historic_name_rec = historic_name_rec[0]

    # was updated?
    if historic_name_rec['opcode'] != 'NAME_UPDATE':
        print "not updated at %s" % update_block
        return False

    if historic_name_rec.get('value_hash', None) != '22' * 20:
        print "wrong value hash: %s" % historic_name_rec.get(
            'value_hash', '(null)')
        return False

    return True
Example #52
0
def check( state_engine ):

    global zonefile_hash

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        print "namespace reveal exists"
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        print "no namespace"
        return False 

    if ns['namespace_id'] != 'test':
        print "wrong namespace"
        return False 
    
    # registered 
    name_rec = state_engine.get_name( "foo.test" )
    if name_rec is None:
        print "name does not exist"
        return False 

    # owned by
    owner_address = wallets[4].addr
    if name_rec['address'] != owner_address or name_rec['sender'] != pybitcoin.make_pay_to_address_script(owner_address):
        print "sender is wrong"
        return False 

    # value hash 
    if name_rec['value_hash'] != zonefile_hash:
        print "wrong zonefile hash: %s != %s" % (name_rec['value_hash'], zonefile_hash)
        return False

    # replicated?
    zonefile = testlib.blockstack_get_zonefile( zonefile_hash )
    if 'error' in zonefile:
        print "zonefile error: %s" % zonefile['error']
        return False

    # right hash?
    if blockstack_client.hash_zonefile( zonefile ) != zonefile_hash:
        print "wrong zonefile: %s != %s" % (blockstack_client.hash_zonefile(zonefile), zonefile_hash)
        return False

    # doesn't show up in listing
    names_owned = testlib.blockstack_rpc_names()
    if 'error' in names_owned:
        print "rpc names: %s" % names_owned['error']
        return False

    if len(names_owned['names_owned']) > 0:
        print "still owned: %s" % names_owned['names_owned']
        return False

    # all queues are drained 
    queue_info = testlib.blockstack_client_queue_state()
    if len(queue_info) > 0:
        print "Still in queue:\n%s" % json.dumps(queue_info, indent=4, sort_keys=True)
        return False

    return True