I don't know anything about Ethereum (or cryptology in general), but from reading the linked document, I don't think your logic is quite right. What you're calling the "addend" is defined as a parity value, which is always either 0 or 1. This is why the spec says that v = CHAIN_ID * 2 + 35
or v = CHAIN_ID * 2 + 36
, which means that CHAIN_ID = (v - {35,36}) / 2
.
This is a complete guess, but I think you can determine the parity simply by knowing whether v
is even or odd. If it's odd, you want to subtract 35, and if it's even, you want to subtract 36, so that in either case you can divide the result exactly by 2.
If this is true, we can rewrite your code like this:
let v = IntTypeDecoder().DecodeBigInteger tx.Signature.V
let parity = (if v % 2 = 0 then 1 else 0)
let chainId = (v - BigInteger (35 + parity)) / BigInteger 2 // no remainder possible
I think you could also make the parity implicit by relying on F#'s integer division to discard the remainder:
let v = IntTypeDecoder().DecodeBigInteger tx.Signature.V
let chainId = (v - BigInteger 35) / BigInteger 2 // ignore remainder
Be careful about off-by-one errors, though. I haven't tested (or even tried to compile) any of this code.
Another caveat: All of the above only seems to apply in certain conditions, such as when nine elements have been hashed, instead of six. I assume you've already accounted for that.