(required by virtualchain state engine)
   
   Save all persistent state to stable storage.
   Called once per block.

   In Blockstack's case, we save transactions as we process them.
   The only thing to do here is to synchronize the Atlas DB and clean up the 
   BlockstackDB instance in preparation for receiving the next blocks' transactions.

   Return True on success
   Return False on failure.

def db_save( block_height, consensus_hash, ops_hash, accepted_ops, virtualchain_ops_hints, db_state=None ):
   """
   (required by virtualchain state engine)
   
   Save all persistent state to stable storage.
   Called once per block.

   In Blockstack's case, we save transactions as we process them.
   The only thing to do here is to synchronize the Atlas DB and clean up the 
   BlockstackDB instance in preparation for receiving the next blocks' transactions.

   Return True on success
   Return False on failure.
   """
   from ..atlas import atlasdb_sync_zonefiles 

   if db_state is not None:

        blockstack_opts = get_blockstack_opts()
        new_zonefile_infos = None

        # vest any tokens for the next block (so they'll be immediately usable in the next block)
        try:
            db_state.commit_account_vesting(block_height+1)
        except Exception as e:
            log.exception(e)
            log.fatal("Failed to vest accounts at {}+1".format(block_height))
            os.abort()

        try:
            # flush the database
            db_state.commit_finished(block_height)
        except Exception as e:
            log.exception(e)
            log.error("FATAL: failed to commit at block %s" % block_height )
            os.abort()
        
        try:
            atlas_state = None
            if hasattr(db_state, 'atlas_state') and db_state.atlas_state is not None:
                # normal course of action 
                atlas_state = db_state.atlas_state

            # sync block data to atlas, if enabled
            if is_atlas_enabled(blockstack_opts):
                log.debug("Synchronize Atlas DB for {}".format(block_height))
                zonefile_dir = blockstack_opts['zonefiles']
                atlasdb_path = blockstack_opts['atlasdb_path']

                # NOTE: set end_block explicitly since db_state.lastblock still points to the previous block height
                gc.collect()
                new_zonefile_infos = atlasdb_sync_zonefiles(db_state, block_height, zonefile_dir, atlas_state, path=atlasdb_path, end_block=block_height+1)
                gc.collect()

        except Exception as e:
            log.exception(e)
            log.error("FATAL: failed to update Atlas db at %s" % block_height )
            os.abort()
        
        try:
            # sync subdomain state for this block range, if enabled
            if is_subdomains_enabled(blockstack_opts):
                subdomain_index = None
                instantiated = False

                if hasattr(db_state, 'subdomain_index') and db_state.subdomain_index is not None:
                    # normal course of action
                    subdomain_index = db_state.subdomain_index
                else:
                    # verifying a database
                    from ..subdomains import SubdomainIndex
                    log.warning("Instantiating subdomain index")
                    subdomain_index = SubdomainIndex(blockstack_opts['subdomaindb_path'], blockstack_opts=blockstack_opts)
                    instantiated = True
               
                log.debug("Synchronize subdomain index for {}".format(block_height))

                gc.collect()
                subdomain_index.index(block_height, block_height+1)
                gc.collect()

                if instantiated:
                    # invalidate 
                    subdomain_index.close()
                    subdomain_index = None

        except Exception as e:
            log.exception(e)
            log.error("FATAL: failed to update subdomains db at {}".format(block_height))
            os.abort()

        return True

   else:
       log.error("FATAL: no state engine given")
       os.abort()