This change makes all fields in a Context instance final to simplify and make the rules clearer. The fields are not meant to be updated as the Context object is propagated in different threads as Thread Local Storage. Even if that mechanism gets removed later, different set of values (in the same process) should be represented as different Context instances.
ECKey violates the equals/hashCode contract for
Java objects. Objects that are equivalent via
the equals method, _must_ have the same hash code.
This is not the case for ECKeys when comparing
the compressed and uncompressed forms of a public key.
The implementation of the `equals` method defines
these objects to be equivalent, but the hashCode
method defined them to be distinct!
Original implementation comes from commit
640db52cf48416db8e2b24b502b3775243ad5162
which contains this bug. [1]
Note that the comment identifies the correct intent:
> Public keys are random already so we can just use a part of them as the hashcode. Read from the start to
> avoid picking up the type code (compressed vs uncompressed) which is tacked on the end.
But the second sentence is incorrect. The first byte (index 0) is the type code
(compressed vs. uncompressed), not “the end”.
The code has since been refactored in commit
9219d8a9b5714cf4e65dc046c70930c86416e65d
but the implementation is effectively
identical. [2]
The fix is simple: use the most-significant four
bytes of the X-coordinate of the public key.
[1](640db52cf4 (diff-b59ef8be77b9148b27a14be59762c0c5R353))
[2](9219d8a9b5 (diff-1849449aac05f7e59de7ebd56efd7f43R1201))
These ctors are the only way to construct a key without a parent
but with a depth that matches the path passed in. The ctors taking
parents set the depth to 0 when parent is null. Whether this is
desirable is not clear; exposing the other ctors seems a lower risk
change given the comments in this file that detail support for depth
not matching the path length.
The use case for this change is interfacing with APIs that allow
derivation of children from a path without returning the intermediate
keys. In this case we have no parent to pass to the ctor but we want
to create a correct DeterministicKey for interop with the rest of bitcoinj.