There does seem to be a lot of excessive locking. For example:
Transaction transaction = Transaction.getTransaction(buffer);
synchronized (Nxt.transactions) {
transaction.index = ++transactionCounter;
}
Since all you are really doing is setting a transaction number, you should be using AtomicInteger. This would eliminate the lock completely
But, in general, you should consider minimizing the scopes of your locks. For example, here, you're locking the entire transactions array to update a single transaction. It would be better to lock around that specific transaction so as not to block other pieces of code attempting to inspect / edit other transactions.
Also, there are a number of places where reader-writer locks are more appropriate than using synchronized (e.g. when dealing users, which should change relatively infrequently).
This extra locking can help scalability down the road.