Replicate one or more zonefiles, given as serialized strings.
        Only stores zone files whose zone file hashes were announced on the blockchain (i.e. not subdomain zone files)
        Returns {'status': True, 'saved': [0|1]'} on success ('saved' is a vector of success/failure)
        Returns {'error': ...} on error
        Takes at most 5 zonefiles

def rpc_put_zonefiles( self, zonefile_datas, **con_info ):
        """
        Replicate one or more zonefiles, given as serialized strings.
        Only stores zone files whose zone file hashes were announced on the blockchain (i.e. not subdomain zone files)
        Returns {'status': True, 'saved': [0|1]'} on success ('saved' is a vector of success/failure)
        Returns {'error': ...} on error
        Takes at most 5 zonefiles
        """
        conf = get_blockstack_opts()
        if not is_atlas_enabled(conf):
            return {'error': 'No data', 'http_status': 400}
        
        if 'zonefiles' not in conf:
            return {'error': 'No zonefiles directory (likely a configuration error)', 'http_status': 400}

        if type(zonefile_datas) != list:
            return {'error': 'Invalid data', 'http_status': 400}

        if len(zonefile_datas) > 5:
            return {'error': 'Too many zonefiles', 'http_status': 400}

        for zfd in zonefile_datas:
            if not check_string(zfd, max_length=((4 * RPC_MAX_ZONEFILE_LEN) / 3) + 3, pattern=OP_BASE64_EMPTY_PATTERN):
                return {'error': 'Invalid zone file payload (exceeds {} bytes and/or not base64-encoded)'.format(RPC_MAX_ZONEFILE_LEN)}

        zonefile_dir = conf.get("zonefiles", None)
        saved = []

        for zonefile_data in zonefile_datas:

            # decode
            try:
                zonefile_data = base64.b64decode( zonefile_data )
            except:
                log.debug("Invalid base64 zonefile")
                saved.append(0)
                continue

            if len(zonefile_data) > RPC_MAX_ZONEFILE_LEN:
                log.debug("Zonefile too long")
                saved.append(0)
                continue
            
            # is this zone file already discovered?
            zonefile_hash = get_zonefile_data_hash(str(zonefile_data))
            zfinfos = atlasdb_get_zonefiles_by_hash(zonefile_hash, path=conf['atlasdb_path'])
            if not zfinfos:
                # nope
                log.debug("Unknown zonefile hash {}".format(zonefile_hash))
                saved.append(0)
                continue
            
            # keep this zone file
            rc = store_atlas_zonefile_data( str(zonefile_data), zonefile_dir )
            if not rc:
                log.error("Failed to store zonefile {}".format(zonefile_hash))
                saved.append(0)
                continue
             
            # mark this zone file as present, so we don't ask anyone else for it
            was_present = atlasdb_set_zonefile_present(zonefile_hash, True, path=conf['atlasdb_path'])
            if was_present:
                # we already got this zone file
                # only process it if it's outside our recovery range 
                recovery_start, recovery_end = get_recovery_range(self.working_dir)
                current_block = virtualchain_hooks.get_last_block(self.working_dir)

                if recovery_start is not None and recovery_end is not None and recovery_end < current_block:
                    # no need to process
                    log.debug("Already have zonefile {}".format(zonefile_hash))
                    saved.append(1)
                    continue

            if self.subdomain_index:
                # got new zonefile
                # let the subdomain indexer know, along with giving it the minimum block height
                min_block_height = min([zfi['block_height'] for zfi in zfinfos])
                log.debug("Enqueue {} from {} for subdomain processing".format(zonefile_hash, min_block_height))
                self.subdomain_index.enqueue_zonefile(zonefile_hash, min_block_height)

            log.debug("Stored new zonefile {}".format(zonefile_hash))
            saved.append(1)

        log.debug("Saved {} zonefile(s)".format(sum(saved)))
        log.debug("Reply: {}".format({'saved': saved}))
        return self.success_response( {'saved': saved} )