So I'm working on a project that will hold bitcoins and of course, security is the most obvious risk/danger.
On advice of the developer we have a specially compiled version of bitcoind (unnecessary RPC calls have been removed, as well as calls that pose a security risk).
That's actually terrible advice, that means you need to maintain your separate fork of bitcoin which will make it much less straightforward to apply patches and security fixes as they come. Choose a strong password for the RPC calls, listen only on the local interface and add some iptables rules on top of it just to be sure. MUCH more secure. If you keep the "send" calls disabling other calls is pointless. If you don't keep them you might as well run a wallet such as armory.
Bitcoind runs under a separate user than the php script. SSH/ftp into the server is only possible with keyfiles.
If you have proper passphrases on the private keys it is a good idea.
All mysql calls are escaped so injection should (hopefully) be covered.
Don't reinvent the wheel, use a framework or a lib that does that for you.
A cold wallet is being implemented so the majority of funds are off-site.
Good.
I toyed with the idea of every database entry having a hash generated from all the data and the hash being periodically verified against the database to check for manipulation. But is this realistic?
No, because if someone can mess with the DB they can mess with the hash.
If you really want to go down that road keep backups and run periodic data comparisons to see if historical data has been altered.
Sensitive information, like email is encrypted and salted. The admin tools are locked to IP addresses as well, although their powers are limited in scope. Users can choose to use Google Authenticator as well.
Encryption is absolutely pointless if you keep the decryption keys on the server.
Agreed that if you are storing information that is sensitive (such as email addresses or other more personal information) then it should be encrypted.
If you need to *index* any such columns then this will make things trickier (although you could create another column for indexing purposes that contains the first x characters provided that isn't going to be a problem application-wise).
That doesn't make sense at all, if you need to query on a column chances are the application needs to be able to decrypt it at will for display or other purposes, meaning you'd have to have the keys on the server which defeats the whole thing.