Use excludeFromJsonDataMap to add an optional owner full name property
to Faster Payments (GBP) accounts, without affecting the trade JSON
contract (for backwards compatibility). This is to fix#3976, that some
banks have started checking the recipient name.
Make the name a non-optional field for _new_ accounts, but display the
details for old Faster Payments accounts in exactly the same way as
before, only showing the extra field in the info popup, account and
trade step views when it is present.
Also update the now misleading payment instructions in the buyer popup.
TODO: Update translations (which probably aren't needed anyway).
Make the default toPersistableMessage() method of PersistableEnvelope
simply delegate to Proto.toProtoMessage for speed, so that stores can
explicitly implement (Threaded|UserThreadMapped)PersistableEnvelope if
they actually need concurrency control.
As part of this, make PeerList implement PersistableEnvelope directly
instead of extending PersistableList, as it is non-critical & cloned on
the user thread prior to storage anyway, so doesn't need be thread-safe.
In this way, only PaymentAccountList & small DAO-related stores extend
PersistableList, so they can all be made user-thread-mapped.
After this change, the only concrete store classes not implementing
(Threaded|UserThreadMapped)PersistableEnvelope are:
AccountAgeWitness, BlindVotePayload, ProposalPayload, SignedWitness,
TradeStatistics2, NavigationPath & PeerList
The first five appear to erroneously implement PersistableEnvelope and
can be cleaned up in a separate commit. The last two are non-critical.
(Make NavigationPath.path an immutable list, for slightly better thread
safety anyway - that way it will never be observed half-constructed.)
Avoid a bottleneck computing the cycle index & calling 'Res.get(..)' for
every block since genesis in the DAO state monitor view, when building
the DaoStateBlockListItem objects, by making the 'height' field lazy. To
do this, pass the cycle index into the constructor using an IntSupplier
and make the height a memoised 'Supplier<String>' with a custom getter.
Also add a unit test to check that the auto-generated equals & hashCode
methods still work as expected, as it isn't totally clear what Lombok
would do when a field type differs from its getter return type.
Since this map is final and every PaymentAccountPayload constructor
initialises it to something nonnull, the @Nullable field annotation is
redundant, so remove it.
Further simplify the code by passing an empty map into the constructor
directly from each subclass constructor, rather than mapping empties to
nulls from each 'proto.getExcludeFromJsonDataMap()' result, then mapping
nulls back to empties in the base constructor. This is safe, since
getExcludeFromJsonDataMap() always returns a nonnull map.
Finally, tidy the code slightly by replacing 'Charset.forName("UTF-8")'
with StandardCharsets.UTF_8 in each PaymentAccountPayload subclass.
With the removal of CoinMarketCap as an exchange rate provider in the
prior commit, the @Order values of the remaining three provider
implementations are non-contiguous. CoinMarketCap was @Order(3) and with
it gone, the remaining order values became 1, 2, 4. This is not a
problem in practice, but could be confusing for future maintainers, so
this commit simply decrements the Poloniex implementation from 4 to 3 in
order to make the values contiguous once again.
This commit also fixes a typo in ExchangeRateProvider's Javadoc.
There are circumstances where input via --appDataDir
will lead to the hiddenservice-directory to be deleted.
Successfully reproduced using
--appDataDir=~/foo
Although the "~" does not get interpreted correctly on
my linux system, it does manage to throw off the
mechanics of sparing the hiddenservice-directory from
being deletd.
Add toProtoMessageSynchronized() default method to PersistableEnvelope,
which performs (blocking) protobuf serialisation in the user thread,
regardless of the calling thread. This should prevent data races like
the ConcurrentModificationException observed in #3752, under the
reasonable assumption that shared persistable objects are only mutated
in the user thread.
Also add a ThreadedPersistableEnvelope sub-interface overriding the
default method above, to let objects which are expensive to serialise
(like DaoStateStore) be selectively serialised in the 'save-file-task-X'
thread as before, but directly synchronised with each mutating op. As
most objects are cheap to serialise, this avoids a noticeable perf drop
without having to track down every mutating method for each store.
In all cases but one, classes implementing ThreadedPersistableEnvelope
are stores like TradeStatistic2Store, with a single ConcurrentHashMap
field. These require no further serialisation, since the map entries are
immutable, so the only mutating operations are map.put(..) calls which
are already synchronised with map reads. (Even if map.values().stream()
sees updates @ different keys happen out-of-order, it should be benign.)
The remaining case is DaoStateStore, which is only ever reset or
modified via a single persist(..) call with a cloned DaoState instance
and hash chain from DaoStateSnapshotService, so there is no aliasing
risk from the various DAO state mutations done in DaoStateService and
elsewhere.
This should fix#3752.
Minor change for consistency: narrow the signature of some remaining
such methods, which have return type 'PersistableEnvelope'.
(This excludes some other cases with return type 'NetworkEnvelope'.)