How is "cumulative PoW" calculated to decide between competing chains? Chain 1 has blocks with targets diff1, diff2, diff3, diff4
Chain 2 has blocks with targets DIFF1 DIFF2 DIFF3
What's the formula to derive the (relative) cumulative proof of works from these chains to find out which one is stronger?
My guess is we take their logarithms and add them up?
First of all, &quot;difficulty&quot; as a concept does not exist in the protocol. It's a unit intended only for human consumption.
Internally, the value that corresponds with it is the target. The target is a 256-bit number, computed for every block, and a block is valid if its hash (interpreted as 256-bit number as well) is less than or equal to the target.
The difficulty is simply defined as the (floating-point, approximate) value of MAX_TARGET / target. MAX_TARGET us (216-1)2208, the maximum possible target (so the lowest difficulty Bitcoin will permit for any block).
To compare chains, a new metric is introduced: work. Work is the expected number of hashing attempts are necessary to construct valid proof-of-work for that block. It is simply 2256 divided by the number of potential hash values that meet the target, namely target + 1. So, the work of a block is defined as 2256 / (target + 1).
The work of a chain is simply the sum of the work values of the blocks in it. This makes sense: we want to make sure that an attacker needs to do as much work as the honest miners needed to produce a valid chain.
At block 678033, with approximate difficulty 23137439666472.1, we have:

Target is 1165190949371886336955396954992052935118810155482873856 (or 0xc2a480000000000000000000000000000000000000000 in hex).
Work is 99376063039054378510219
Cumulative work (sum of all work in the entire chain) is approximately 8.565487⋅1027.

So - perhaps remarkably - this is (approximately) equivalent to just summing the difficulty values of all blocks. No logarithms involved.
For completeness, Bitcoin Core's current rules for picking the best chain:

First exclude all chains with invalid blocks
Then pick the tips of all those chains, and leave only the ones with the highest cumulative work (which may be more than one if there is a fork).
Among those, pick the one for which the full block (not just the header) was received first.