In how far does a re-implementation have to reproduce weird behaviour (not quite the same as bugs)?
In order to avoid chain forks, multiple implementations have to reproduce the same behavior exactly. Even the slightest difference can cause a chain fork. There are certainly some cases that can be considered weird behavior, but there are also some issues I would consider outright bugs.
For example, the transaction script language has a well-defined set of allowed opcodes. However, it doesn't check the scripts for invalid opcodes until it actually executes them. This means that you can craft valid scripts which have invalid and nearly arbitrary data in dead execution branches. This is an outright bug in my mind. There are also a couple of other things in the transaction scripts which are indisputable bugs.
In how far are these documented at all?
The exact rules are not really documented anywhere from what I could find. The wiki entry for the wire protocol is fairly accurate, but the block acceptance rules are largely undocumented. There is a wiki entry for the block acceptance rules, but it's not very accurate and doesn't provide sufficient depth. However, I don't believe a publicly editable wiki is the right place for something as important as the protocol and block acceptance rules anyways.
This is an area I believe really needs to be improved. Unfortunately, the general consensus I have seen amongst the core bitcoind devs seems to be "the code is the spec". I would be happy if my take on what the general consensus appears to be is wrong. I fully understand that writing documentation and specs is not glamorous nor fun work, but I think it's paramount for the longtime survival and growth of Bitcoin as it directly plays into multiple implementations. I can't imagine the internet would be anywhere near what it is today if there weren't legitimate specs for things like TCP/IP and instead everyone that implemented a stack had to just go read and properly interpret some mostly undocumented code. Unfortunately, even if a spec is written, unless the majority implementations (realistically this is only bitcoind currently) choose to follow it, it is meaningless.
On the plus side, there is a block tester tool that does a pretty good job of testing the block acceptance rules programatically. While this doesn't eliminate the need for a spec by any means, it is definitely an excellent tool that helps support multiple implementations and would be a fantastic supplement to a real spec.
Does btcd have a different concurrency model?
Yes. Since it is written in Go, btcd uses CSP (Communicating Sequential Processes) heavily for concurrency. The Go mantra is "Do not communicate by sharing memory; instead, share memory by communicating", which is the model btcd strives to follow. For example, in btcd, the server, block manager, and peers are all separate entities running in different goroutines that use channels to communicate with one another. This provides a clear concurrency model with a clean and concise data flow.
How much of the security depends on the go-lang libs themselves?
I'm not really sure what area of security you are referring to here. If you're referring to security issues such as exploitability of the software, I would argue that libraries written in Go eliminate an entire class of the most common causes of vulnerabilities such as stack corruption, heap corruption, uninitialized variable use, use of freed variables, and invalid frees. This is because Go is garbage collected, all variables are initialized to their respective zero values by default, all array accesses are bounds checked by the run-time, and pointer arithmetic is disallowed. That is not to say they're fully immune to exploits of course, but eliminating the vast majority of the most common ones by default is quite nice.
On the other hand, if you're referring more to the security issues such as coin theft, that has less to do with the implementation language and more to do with things like private key management, trusting third parties with your wallet, etc.
It took me about half a man year to reach feature parity in Java though - passing the block tests used by satoshi and bitcoinj - thereafter I worked mostly on higher level projects using the code in production.
Thanks grau. Reaching feature parity in that time frame is an impressive one-man effort. Well done! That sounds very close to what it would have taken us as well to just implement everything without the architectural changes, drive for 100% test coverage in the core packages, and heavy focus on producing fully-documented reusable development components for the community as a part of the process. I'm really glad you posted your stats as I think this goes to show that while it's definitely complicated, it's not something that is so complicated that nobody else should bother as some comments have suggested.