예제 #1
0
def remove_cached_zonefile_data(zonefile_hash, zonefile_dir=None):
    """
    Remove a cached zonefile.
    Idempotent; returns True if deleted or it didn't exist.
    Returns False on error
    """
    if zonefile_dir is None:
        zonefile_dir = get_zonefile_dir()

    if not os.path.exists(zonefile_dir):
        return True

    zonefile_hash = get_zonefile_data_hash(zonefile_data)
    zonefile_path = cached_zonefile_path(zonefile_dir, zonefile_hash)
    zonefile_path_legacy = cached_zonefile_path_legacy(zonefile_dir,
                                                       zonefile_hash)

    for zfp in [zonefile_path, zonefile_path_legacy]:
        if not os.path.exists(zonefile_path):
            continue

        try:
            os.unlink(zonefile_path)
        except:
            log.error("Failed to unlink zonefile %s (%s)" %
                      (zonefile_hash, zonefile_path))
            return False

    return True
예제 #2
0
def store_cached_zonefile_data(zonefile_data, zonefile_dir=None):
    """
    Store a validated zonefile.
    zonefile_data should be a dict.
    The caller should first authenticate the zonefile.
    Return True on success
    Return False on error
    """
    if zonefile_dir is None:
        zonefile_dir = get_zonefile_dir()

    if not os.path.exists(zonefile_dir):
        os.makedirs(zonefile_dir, 0700)

    zonefile_hash = get_zonefile_data_hash(zonefile_data)

    # only store to the latest supported directory
    zonefile_path = cached_zonefile_path(zonefile_dir, zonefile_hash)
    zonefile_dir_path = os.path.dirname(zonefile_path)

    if not os.path.exists(zonefile_dir_path):
        os.makedirs(zonefile_dir_path)

    try:
        with open(zonefile_path, "w") as f:
            f.write(zonefile_data)
            f.flush()
            os.fsync(f.fileno())

    except Exception, e:
        log.exception(e)
        return False
def store_cached_zonefile_data( zonefile_data, zonefile_dir=None ):
    """
    Store a validated zonefile.
    zonefile_data should be a dict.
    The caller should first authenticate the zonefile.
    Return True on success
    Return False on error
    """
    if zonefile_dir is None:
        zonefile_dir = get_zonefile_dir()

    if not os.path.exists(zonefile_dir):
        os.makedirs(zonefile_dir, 0700 )

    zonefile_hash = get_zonefile_data_hash( zonefile_data )
    
    # only store to the latest supported directory
    zonefile_path = cached_zonefile_path( zonefile_dir, zonefile_hash )
    zonefile_dir_path = os.path.dirname(zonefile_path)

    if not os.path.exists(zonefile_dir_path):
        os.makedirs(zonefile_dir_path)

    try:
        with open( zonefile_path, "w" ) as f:
            f.write(zonefile_data)
            f.flush()
            os.fsync(f.fileno())
    except Exception, e:
        log.exception(e)
        return False
def remove_cached_zonefile_data( zonefile_hash, zonefile_dir=None ):
    """
    Remove a cached zonefile.
    Idempotent; returns True if deleted or it didn't exist.
    Returns False on error
    """
    if zonefile_dir is None:
        zonefile_dir = get_zonefile_dir()

    if not os.path.exists(zonefile_dir):
        return True

    zonefile_hash = get_zonefile_data_hash( zonefile_data )
    zonefile_path = cached_zonefile_path( zonefile_dir, zonefile_hash )
    zonefile_path_legacy = cached_zonefile_path_legacy( zonefile_dir, zonefile_hash )

    for zfp in [zonefile_path, zonefile_path_legacy]:
        if not os.path.exists(zonefile_path):
            continue

        try:
            os.unlink(zonefile_path)
        except:
            log.error("Failed to unlink zonefile %s (%s)" % (zonefile_hash, zonefile_path))
            return False

    return True
예제 #5
0
def remove_cached_zonefile_data(zonefile_hash, zonefile_dir=None):
    """
    Remove a cached zonefile 
    """
    if zonefile_dir is None:
        zonefile_dir = get_zonefile_dir()

    if not os.path.exists(zonefile_dir):
        return True

    zonefile_hash = get_zonefile_data_hash(zonefile_data)
    zonefile_dir_path = cached_zonefile_dir(zonefile_dir, zonefile_hash)
    if not os.path.exists(zonefile_dir_path):
        return True

    zonefile_path = os.path.join(zonefile_dir_path, "zonefile.txt")
    if not os.path.exists(zonefile_path):
        return True

    try:
        os.unlink(zonefile_path)
    except:
        log.error("Failed to unlink zonefile %s (%s)" %
                  (zonefile_hash, zonefile_path))
        return False

    return True
def make_zonefile_hash(name, address, index=0):
    """
    Make the appropriate zone file hash
    """
    zonefile_data = make_zonefile(name, address, index=index)
    zonefile_hash = blockstack_client.get_zonefile_data_hash(zonefile_data)
    return zonefile_hash
예제 #7
0
def verify_zonefile( zonefile_str, value_hash ):
    """
    Verify that a zonefile hashes to the given value hash
    @zonefile_str must be the zonefile as a serialized string
    """
    zonefile_hash = get_zonefile_data_hash( zonefile_str )
    if zonefile_hash != value_hash:
        log.debug("Zonefile hash mismatch: expected %s, got %s" % (value_hash, zonefile_hash))
        return False 

    return True
def get_zonefile_data_from_storage( name, zonefile_hash, drivers=None ):
    """
    Get a serialized zonefile from our storage drivers.
    Return the zonefile dict on success.
    Raise on error
    """
    log.debug("Get zonefile {} for {} using '{}'".format(zonefile_hash, name, ",".join(drivers if drivers is not None else ["(all)"])))
    zonefile_txt = blockstack_client.storage.get_immutable_data( zonefile_hash, hash_func=blockstack_client.get_blockchain_compat_hash, fqu=name, zonefile=True, drivers=drivers )
    if zonefile_txt is None:
        raise Exception("Failed to get valid zonefile data")

    # verify
    if get_zonefile_data_hash( zonefile_txt ) != zonefile_hash:
        log.warn("Corrupted zonefile for '%s'" % name)
        raise Exception("Corrupt zonefile")
   
    return zonefile_txt
예제 #9
0
def get_zonefile_data_from_storage( name, zonefile_hash, drivers=None ):
    """
    Get a serialized zonefile from our storage drivers.
    Return the zonefile dict on success.
    Raise on error
    """
    log.debug("Get zonefile {} for {} using '{}'".format(zonefile_hash, name, ",".join(drivers if drivers is not None else ["(all)"])))
    zonefile_txt = blockstack_client.storage.get_immutable_data( zonefile_hash, hash_func=blockstack_client.get_blockchain_compat_hash, fqu=name, zonefile=True, drivers=drivers )
    if zonefile_txt is None:
        raise Exception("Failed to get valid zonefile data")

    # verify
    if get_zonefile_data_hash( zonefile_txt ) != zonefile_hash:
        log.warn("Corrupted zonefile for '%s'" % name)
        raise Exception("Corrupt zonefile")
   
    return zonefile_txt
예제 #10
0
def get_zonefile_data_from_storage(name, zonefile_hash, drivers=None):
    """
    Get a serialized zonefile from our storage drivers.
    Return the zonefile dict on success.
    Raise on error
    """
    zonefile_txt = blockstack_client.storage.get_immutable_data(
        zonefile_hash,
        hash_func=blockstack_client.get_blockchain_compat_hash,
        fqu=name,
        zonefile=True,
        drivers=drivers)
    if zonefile_txt is None:
        raise Exception("Failed to get valid zonefile data")

    # verify
    if get_zonefile_data_hash(zonefile_txt) != zonefile_hash:
        log.warn("Corrupted zonefile for '%s'" % name)
        raise Exception("Corrupt zonefile")

    return zonefile_txt
예제 #11
0
def store_zonefile_data_to_storage(zonefile_text,
                                   txid,
                                   required=None,
                                   skip=None,
                                   cache=False,
                                   zonefile_dir=None,
                                   tx_required=True):
    """
    Upload a zonefile to our storage providers.
    Return True if at least one provider got it.
    Return False otherwise.
    """
    if tx_required and txid is None:
        log.error("No txid for zonefile hash '%s'" % (zonefile_hash))
        return False

    zonefile_hash = get_zonefile_data_hash(zonefile_text)

    if cache:
        rc = store_cached_zonefile_data(zonefile_text,
                                        zonefile_dir=zonefile_dir)
        if not rc:
            log.debug("Failed to cache zonefile %s" % zonefile_hash)

    # NOTE: this can fail if one of the required drivers needs a non-null txid
    res = blockstack_client.storage.put_immutable_data(zonefile_text,
                                                       txid,
                                                       data_hash=zonefile_hash,
                                                       required=required,
                                                       skip=skip,
                                                       required_exclusive=True)
    if res is None:
        log.error("Failed to store zonefile '%s' for '%s'" %
                  (zonefile_hash, txid))
        return False

    return True
def store_zonefile_data_to_storage( zonefile_text, txid, required=None, skip=None, cache=False, zonefile_dir=None, tx_required=True ):
    """
    Upload a zonefile to our storage providers.
    Return True if at least one provider got it.
    Return False otherwise.
    """
    if tx_required and txid is None:
        log.error("No txid for zonefile hash '%s'" % (zonefile_hash))
        return False

    zonefile_hash = get_zonefile_data_hash( zonefile_text )
    
    if cache:
        rc = store_cached_zonefile_data( zonefile_text, zonefile_dir=zonefile_dir )
        if not rc:
            log.debug("Failed to cache zonefile %s" % zonefile_hash)

    # NOTE: this can fail if one of the required drivers needs a non-null txid
    res = blockstack_client.storage.put_immutable_data( zonefile_text, txid, data_hash=zonefile_hash, required=required, skip=skip, required_exclusive=True )
    if res is None:
        log.error("Failed to store zonefile '%s' for '%s'" % (zonefile_hash, txid))
        return False

    return True
def scenario(wallets, **kw):

    global first_name_block
    test_proxy = testlib.make_proxy()

    # make a test namespace
    resp = testlib.blockstack_namespace_preorder("test", wallets[1].addr,
                                                 wallets[0].privkey)
    if 'error' in resp:
        print json.dumps(resp, indent=4)
        return False

    testlib.next_block(**kw)  # end of 689

    resp = testlib.blockstack_namespace_reveal(
        "test", wallets[1].addr, 2, 250, 4,
        [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10,
        wallets[0].privkey)
    if 'error' in resp:
        print json.dumps(resp, indent=4)
        return False

    testlib.next_block(**kw)  # 690

    # make a zonefile and a profile
    driver_urls = blockstack_client.storage.make_mutable_data_urls(
        'foo.test', use_only=['dht', 'disk'])
    zonefile = blockstack_client.zonefile.make_empty_zonefile(
        'foo.test', wallets[4].pubkey_hex, urls=driver_urls)
    zonefile_txt = blockstack_zones.make_zone_file(zonefile,
                                                   origin='foo.test',
                                                   ttl=4200)

    # make a new keyfile as well
    user_profile = blockstack_client.user.make_empty_user_profile()
    '''
    res = blockstack_client.key_file.make_initial_key_file(user_profile, wallets[3].privkey)
    if 'error' in res:
        print res
        return res

    keyfile_txt = res['key_file']
    '''
    zonefile_hash = blockstack_client.get_zonefile_data_hash(zonefile_txt)

    resp = testlib.blockstack_name_import("foo.test", wallets[3].addr,
                                          zonefile_hash, wallets[1].privkey)
    if 'error' in resp:
        print json.dumps(resp, indent=4)
        return False

    testlib.next_block(**kw)  # 691

    # broadcast zonefile
    res = testlib.blockstack_cli_sync_zonefile('foo.test',
                                               zonefile_string=zonefile_txt)
    if 'error' in res:
        print res
        return False
    '''
    # upload keyfile
    res = blockstack_client.key_file.key_file_put('foo.test', keyfile_txt)
    if 'error' in res:
        print res
        return False
    '''

    rc = blockstack_client.profile.put_profile(
        'foo.test',
        user_profile,
        blockchain_id='foo.test',
        user_data_privkey=wallets[4].privkey,
        user_zonefile=zonefile,
        proxy=test_proxy)
    if not rc:
        print 'failed to put profile'
        return False

    # try lookup
    res = testlib.blockstack_cli_lookup('foo.test')
    if 'error' in res:
        print res
        return False

    first_name_block = testlib.get_current_block(**kw)

    resp = testlib.blockstack_namespace_ready("test", wallets[1].privkey)
    if 'error' in resp:
        print json.dumps(resp, indent=4)
        return False

    # try lookup
    res = testlib.blockstack_cli_lookup('foo.test')
    if 'error' in res:
        print res
        return False

    testlib.next_block(**kw)  # end of 692

    whois = testlib.blockstack_cli_whois('foo.test')
    if 'error' in whois:
        print 'failed to whois foo.test'
        print json.dumps(whois, indent=4)
        return False

    # this should be the second-to-last block
    if whois['expire_block'] != testlib.get_current_block(**kw) + 2:
        print 'wrong expire block (expect 2 more)'
        print whois
        return False

    # try lookup
    res = testlib.blockstack_cli_lookup('foo.test')
    if 'error' in res:
        print res
        return False

    testlib.next_block(**kw)  # end of 693; begin epoch 2
    # begin epoch 2

    # try lookup
    res = testlib.blockstack_cli_lookup('foo.test')
    if 'error' in res:
        print res
        return False

    testlib.next_block(**kw)  # 694

    # try lookup
    res = testlib.blockstack_cli_lookup('foo.test')
    if 'error' in res:
        print res
        return False

    whois = testlib.blockstack_cli_whois('foo.test')
    if 'error' in whois:
        print 'failed to whois foo.test'
        print json.dumps(whois, indent=4)
        return False

    # this should be the last block
    if whois['expire_block'] != testlib.get_current_block(**kw) + 2:
        print 'wrong expire block (expect 2 more)'
        print whois
        return False

    if whois['renewal_deadline'] != testlib.get_current_block(**kw) + 2:
        print 'wrong renewal block (expect 2 more)'
        print whois
        return False

    print whois

    testlib.next_block(**kw)  # 695 (epoch 3 begins)

    # try lookup
    res = testlib.blockstack_cli_lookup('foo.test')
    if 'error' in res:
        print res
        return False

    testlib.next_block(**kw)  # end of 696

    # try lookup (should fail)
    res = testlib.blockstack_cli_lookup('foo.test')
    if 'error' not in res:
        print res
        return False

    if 'expired' not in res['error']:
        print res
        return False

    whois = testlib.blockstack_cli_whois('foo.test')
    if 'error' in whois:
        print whois
        return False

    # this should be the expire block
    if whois['expire_block'] != testlib.get_current_block(**kw):
        print 'wrong expire block (now at {})'.format(
            testlib.get_current_block(**kw))
        print whois
        return False

    # should now be a grace period
    if whois['renewal_deadline'] != testlib.get_current_block(**kw) + 5:
        print 'wrong renewal block (now at {})'.format(
            testlib.get_current_block(**kw))
        print whois
        return False

    last_transaction_height = whois['last_transaction_height']

    # begin epoch 3 (grace period)
    testlib.next_block(**kw)  # end of 697

    # try lookup (should fail)
    res = testlib.blockstack_cli_lookup('foo.test')
    if 'error' not in res:
        print res
        return False

    if 'expired' not in res['error']:
        print res
        return False

    testlib.next_block(**kw)  # 698

    # try lookup (should fail)
    res = testlib.blockstack_cli_lookup('foo.test')
    if 'error' not in res:
        print res
        return False

    if 'expired' not in res['error']:
        print res
        return False

    testlib.next_block(**kw)  # 699

    # try lookup (should fail)
    res = testlib.blockstack_cli_lookup('foo.test')
    if 'error' not in res:
        print res
        return False

    if 'expired' not in res['error']:
        print res
        return False

    testlib.next_block(**kw)  # 700

    # try lookup (should fail)
    res = testlib.blockstack_cli_lookup('foo.test')
    if 'error' not in res:
        print res
        return False

    if 'expired' not in res['error']:
        print res
        return False

    # make a zonefile and a profile
    driver_urls = blockstack_client.storage.make_mutable_data_urls(
        'foo.test', use_only=['dht', 'disk'])
    new_zonefile = blockstack_client.zonefile.make_empty_zonefile(
        'foo.test', wallets[4].pubkey_hex, urls=driver_urls)
    new_zonefile_txt = blockstack_zones.make_zone_file(new_zonefile,
                                                       origin='foo.test',
                                                       ttl=4200)

    # make a new keyfile as well
    new_user_profile = blockstack_client.user.make_empty_user_profile()
    new_user_profile['new_user'] = True
    '''
    res = blockstack_client.key_file.make_initial_key_file(new_user_profile, wallets[0].privkey)
    if 'error' in res:
        print res
        return res

    new_keyfile_txt = res['key_file']
    '''
    new_zonefile_hash = blockstack_client.get_zonefile_data_hash(
        new_zonefile_txt)

    rc = blockstack_client.profile.put_profile(
        'foo.test',
        new_user_profile,
        blockchain_id='foo.test',
        user_data_privkey=wallets[4].privkey,
        user_zonefile=new_zonefile,
        proxy=test_proxy)
    if not rc:
        print 'failed to put profile'
        return False

    # renew/xfer/update
    resp = testlib.blockstack_name_renew('foo.test',
                                         wallets[3].privkey,
                                         zonefile_hash=new_zonefile_hash,
                                         recipient_addr=wallets[0].addr)
    if 'error' in resp:
        print resp
        return False

    testlib.next_block(**kw)  # end of 701 (end of grace period)

    # try lookup (should succeed again)
    res = testlib.blockstack_cli_lookup('foo.test')
    if 'error' in res:
        print res
        return False

    if res['zonefile'] != new_zonefile_txt:
        print 'wrong zonefile'
        print new_zonefile_txt
        print res
        return False

    testlib.next_block(**kw)  # 702 (name can be registered again)
예제 #14
0
    Return False on error
    """
    if zonefile_dir is None:
        zonefile_dir = get_zonefile_dir()

    if not os.path.exists(zonefile_dir):
        os.makedirs(zonefile_dir, 0700)

    try:
        zonefile_data = blockstack_zones.make_zone_file(zonefile_dict)
    except Exception, e:
        log.exception(e)
        log.error("Invalid zonefile dict")
        return False

    zonefile_hash = blockstack_client.get_zonefile_data_hash(zonefile_data)
    zonefile_dir_path = cached_zonefile_dir(zonefile_dir, zonefile_hash)
    if not os.path.exists(zonefile_dir_path):
        os.makedirs(zonefile_dir_path)

    zonefile_path = os.path.join(zonefile_dir_path, "zonefile.txt")
    try:
        with open(zonefile_path, "w") as f:
            f.write(zonefile_data)
            f.flush()
            os.fsync(f.fileno())
    except Exception, e:
        log.exception(e)
        return False

    return True
예제 #15
0
    Return False on error
    """
    if zonefile_dir is None:
        zonefile_dir = get_zonefile_dir()

    if not os.path.exists(zonefile_dir):
        os.makedirs(zonefile_dir, 0700 )

    try:
        zonefile_data = blockstack_zones.make_zone_file( zonefile_dict )
    except Exception, e:
        log.exception(e)
        log.error("Invalid zonefile dict")
        return False

    zonefile_hash = blockstack_client.get_zonefile_data_hash( zonefile_data )
    zonefile_dir_path = cached_zonefile_dir( zonefile_dir, zonefile_hash )
    if not os.path.exists(zonefile_dir_path):
        os.makedirs(zonefile_dir_path)

    zonefile_path = os.path.join(zonefile_dir_path, "zonefile.txt")
    try:
        with open( zonefile_path, "w" ) as f:
            f.write(zonefile_data)
            f.flush()
            os.fsync(f.fileno())
    except Exception, e:
        log.exception(e)
        return False
        
    return True
def scenario(wallets, **kw):

    wallet = testlib.blockstack_client_initialize_wallet(
        "0123456789abcdef", wallets[2].privkey, wallets[3].privkey,
        wallets[4].privkey)

    testlib.blockstack_namespace_preorder("test", wallets[1].addr,
                                          wallets[0].privkey)
    testlib.next_block(**kw)

    testlib.blockstack_namespace_reveal(
        "test", wallets[1].addr, 52595, 250, 4,
        [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10,
        wallets[0].privkey)
    testlib.next_block(**kw)

    testlib.blockstack_namespace_ready("test", wallets[1].privkey)
    testlib.next_block(**kw)

    testlib.blockstack_name_preorder("foo1.test", wallets[2].privkey,
                                     wallets[3].addr)
    testlib.blockstack_name_preorder("foo2.test", wallets[2].privkey,
                                     wallets[3].addr)
    testlib.blockstack_name_preorder("foo3.test", wallets[2].privkey,
                                     wallets[3].addr)
    testlib.next_block(**kw)

    # make zonefiles:
    # one with a data key
    # one without a data key
    # one with a nonstandard zonefile
    zf1 = blockstack_client.zonefile.make_empty_zonefile(
        'foo1.test', wallets[4].pubkey_hex)
    zf1_txt = blockstack_zones.make_zone_file(zf1)

    zf2 = blockstack_client.zonefile.make_empty_zonefile('foo2.test', None)
    zf2_txt = blockstack_zones.make_zone_file(zf2)

    zf3_txt = '\x00\x01\x02\x03\x04\x05'

    testlib.blockstack_name_register(
        "foo1.test",
        wallets[2].privkey,
        wallets[3].addr,
        zonefile_hash=blockstack_client.get_zonefile_data_hash(zf1_txt))
    testlib.blockstack_name_register(
        "foo2.test",
        wallets[2].privkey,
        wallets[3].addr,
        zonefile_hash=blockstack_client.get_zonefile_data_hash(zf2_txt))
    testlib.blockstack_name_register(
        "foo3.test",
        wallets[2].privkey,
        wallets[3].addr,
        zonefile_hash=blockstack_client.get_zonefile_data_hash(zf3_txt))
    testlib.next_block(**kw)

    # replicate zonefiles
    proxy = testlib.make_proxy()
    res = blockstack_client.proxy.put_zonefiles("localhost:{}".format(
        blockstack.RPC_SERVER_PORT), [
            base64.b64encode(zf1_txt),
            base64.b64encode(zf2_txt),
            base64.b64encode(zf3_txt)
        ],
                                                proxy=proxy)
    if 'error' in res:
        print res
        return False

    for s in res['saved']:
        if s != 1:
            print res
            return False

    print 'waiting for zonefiles to be saved...'
    time.sleep(5)

    # store signed profile for each
    working_dir = kw['working_dir']

    for name in ['foo1.test', 'foo2.test', 'foo3.test']:
        profile = blockstack_client.user.make_empty_user_profile()
        profile['name'] = name

        profile_path = os.path.join(working_dir, '{}.profile'.format(name))
        with open(profile_path, 'w') as f:
            f.write(json.dumps(profile))

        print 'sign profile for {}'.format(name)

        jwt = testlib.blockstack_cli_sign_profile(name, profile_path)
        if 'error' in jwt:
            print jwt
            return False

        jwt_path = os.path.join(working_dir, '{}.profile.jwt'.format(name))
        with open(jwt_path, 'w') as f:
            f.write(jwt)

        print 'verify profile for {}'.format(name)

        res = testlib.blockstack_cli_verify_profile(name, jwt_path)
        if 'error' in res:
            print res
            return False

        print 'store profile for {}'.format(name)

        # store the jwt to the right place
        res = blockstack_client.storage.put_mutable_data(name,
                                                         jwt,
                                                         sign=False,
                                                         profile=True,
                                                         raw=True)
        if not res:
            print res
            return False

        print 'lookup profile for {}'.format(name)

        # lookup
        res = testlib.blockstack_cli_lookup(name)
        if name != 'foo3.test':
            if 'error' in res:
                print res
                return False

            if res['profile'] != profile:
                print 'profile mismatch:'
                print res
                print profile
                return False

        else:
            if 'error' not in res:
                print res
                return False
예제 #17
0
def scenario( wallets, **kw ):

    # valid 500kb + 1 XMLRPC, should be rejected
    xmlmsg = make_xml_call(512 * 1024 + 1)

    print '\ntest too big\n'

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(("localhost", blockstack.RPC_SERVER_PORT))
    s.send(xmlmsg)
    buf = s.recv(16384)

    if 'HTTP/1.0 400' not in buf:
        print buf
        return False
    
    # valid 500kb + 1 XMLRPC gzipp'ed, should be rejected
    xmlmsg = make_xml_call(512 * 1024 + 1, gzipped=True)

    print '\ntest too big, gzipped\n'

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(("localhost", blockstack.RPC_SERVER_PORT))
    s.send(xmlmsg)
    buf = s.recv(16384)

    if 'HTTP/1.0 501' not in buf:
        print buf
        return False

    # valid 500kb XMLRPC, should be accepted
    xmlmsg = make_xml_call(512 * 1024)

    print '\ntest just big enough\n'

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(("localhost", blockstack.RPC_SERVER_PORT))
    s.send(xmlmsg)
    buf = s.recv(16384)

    if 'HTTP/1.0 200' not in buf:
        print buf
        return False

    # valid 500kb XMLRPC gzipped, should be rejected
    xmlmsg = make_xml_call(512 * 1024, gzipped=True)

    print '\ntest just big enough, gzipped\n'

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(("localhost", blockstack.RPC_SERVER_PORT))
    s.send(xmlmsg)
    buf = s.recv(16384)

    if 'HTTP/1.0 501' not in buf:
        print buf
        return False

    big_zonefile = '0' * 40960
    big_zonefile_2 = '1' * 40960
    big_zonefile_nack = '2' * 40961

    # make some zonefiles
    testlib.blockstack_namespace_preorder( "test", wallets[1].addr, wallets[0].privkey )
    testlib.next_block( **kw )

    testlib.blockstack_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0], 10, 10, wallets[0].privkey )
    testlib.next_block( **kw )

    testlib.blockstack_namespace_ready( "test", wallets[1].privkey )
    testlib.next_block( **kw )

    testlib.blockstack_name_preorder( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )

    testlib.blockstack_name_register( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )

    zonefile_hash = blockstack_client.get_zonefile_data_hash(big_zonefile)
    testlib.blockstack_name_update("foo.test", zonefile_hash, wallets[3].privkey)
    testlib.next_block(**kw)

    srv = xmlrpclib.ServerProxy("http://localhost:{}".format(blockstack.RPC_SERVER_PORT))
    res = srv.put_zonefiles([base64.b64encode(big_zonefile)])
    res = json.loads(res)
    if 'error' in res:
        print 'failed to put {}'.format(zonefile_hash)
        print res
        return False

    # ask for zonefile
    res = srv.get_zonefiles([zonefile_hash])
    res = json.loads(res)
    if 'error' in res:
        print 'failed to get {}'.format(zonefile_hash)
        print res
        return False

    zonefile_hash_2 = blockstack_client.get_zonefile_data_hash(big_zonefile_2)
    testlib.blockstack_name_update("foo.test", zonefile_hash_2, wallets[3].privkey)
    testlib.next_block(**kw)

    res = srv.put_zonefiles([base64.b64encode(big_zonefile_2)])
    res = json.loads(res)
    if 'error' in res:
        print 'failed to put {}'.format(zonefile_hash_2)
        print res
        return False
 
    # ask for zonefile
    res = srv.get_zonefiles([zonefile_hash_2])
    res = json.loads(res)
    if 'error' in res:
        print 'failed to get {}'.format(zonefile_hash_2)
        print res
        return False

    zonefile_hash_nack = blockstack_client.get_zonefile_data_hash(big_zonefile_nack)
    testlib.blockstack_name_update("foo.test", zonefile_hash_nack, wallets[3].privkey)
    testlib.next_block(**kw)

    res = srv.put_zonefiles([base64.b64encode(big_zonefile_nack)])
    res = json.loads(res)
    if 'error' in res:
        print 'failed to put {}'.format(zonefile_hash_nack)
        print res
        return False

    if res['saved'][0] != 0:
        print 'accidentally saved {}'.format(zonefile_hash_nack)
        print res
        return False

    # should be unavailable 
    res = srv.get_zonefiles([zonefile_hash_nack])
    res = json.loads(res)
    if 'error' in res:
        print 'failed to query'
        print res
        return False

    if len(res['zonefiles']) > 0:
        print 'accidentally fetched big zonefile'
        print res
        return False

    # should fail, since the RPC was too big
    try:
        res = srv.get_zonefiles([zonefile_hash, zonefile_hash_2])
            
        print 'accidentally exceeded RPC'
        print res
        return False
    except ValueError as ve:
        # should be a value error from defusedxml
        pass
    except Exception:
        raise