Basic transactional DDL script in PostgreSQL
if any errors, roll the whole thing back;


It's simpler than you seem to think. Any exception in a transaction (that is not trapped somehow) triggers a ROLLBACK for the whole transaction automatically. You don't have to do anything extra.

BEGIN;
CREATE TABLE IF NOT EXISTS blah ( ... );
-- much more DDL
COMMIT;

You cannot start, commit or roll back transactions inside plpgsql at all, since a plpgsql block is always run in the context of an outer transaction automatically.

Don't confuse SQL commands for transaction management with elements of a plpgsql code block. BEGIN is used as keyword in both, that's the only thing in common. That's never ambiguous, because the SQL command is not available inside plpgsql code and there are no plpgsql commands outside plpgsql code blocks.

An EXCEPTION clause in a plpgsql block is only used to trap errors and do something before or instead of the ROLLBACK. Of course, it only makes sense to do something that ROLLBACK isn't going to undo - like raising a message which is never rolled back.
You don't need any of this for your demonstrated code.