Add a nested class of lazy fields to (Deposit|Transactions)ListItem,
together with an associated memoised Supplier, lazyFieldsSupplier, which
initialises them all the first time any one of them is requested. Move
the txConfidenceIndicator & tooltip fields to this class, so that they
are only loaded when the given address/tx row is displayed in the
deposit/transactions views, respectively.
This prevents a minor bottleneck, as profiling indicates that creating a
tooltip for each tx confidence indicator in the list is quite expensive
and takes up around half the rendering time. (There may be 1000's of txs
or addresses in an old wallet.)
Fix a serious memory leak in DepositListItem due to missing removal of
the BalanceListener (one per item) from BtcWalletService. This prevented
GC of the entire list of items, which was observed to leak ~500 MB in
JProfiler after repeated switching (several dozen times) between tabs.
Attempt to remove a bottleneck during the transactions view load, as
revealed by JProfiler, by optimising the code to determine if any given
transaction and trade are related. Since both these sets will tend to
grow linearly with time, causing quadratic slowdown of TransactionsView,
try to alleviate (without completely fixing) the problem.
To do this, add a cached set of disputed trade IDs to DisputeListService
so that TransactionAwareTradable.is(Dispute|RefundPayout)Tx can be made
O(1) in the common case that the given trade is not involved in any
dispute. Also avoid calling Sha256Hash::toString by passing tx IDs as
Sha256Hash objects directly to is(Deposit|Payout)Tx, and short circuit
an expensive call BtcWalletService.getTransaction in isDelayedPayoutTx,
in the common case, by pre-checking the transaction locktime.
This also fixes a bug in isRefundPayoutTx whereby it incorrectly returns
false if there are >1 disputes in the list returned by RefundManager but
the given trade is not involved in the last one.
Use a guava SetMultimap (a many-to-many mapping without duplicates) to
cache the set of live txs in the user's wallet with a given address as
an input or output. As with the cache of output counts from the previous
commit, compute all the tx sets in one go (by a tx stream followed by a
map inverse) and store in an ImmutableSetMultimap<Address, Transaction>,
invalidating the entire cache immediately upon each wallet change event.
This is to fix another (larger) quadratic time bug in DepositView, when
getting the confidence (i.e. confirmation count) of each wallet address.
Also simplify getTransactionConfidence & onTransactionConfidenceChanged
methods slightly, which generated (possibly unintentionally) repeating &
singleton lists of TransactionConfidence objects to pass to
WalletService.getMostRecentConfidence(..) respectively.
Use a guava Multiset to cache the total number of tx outputs (out of the
live txs in the user's wallet) with a given address. Since this requires
a scan of the entire tx set, compute all the counts in one go and store
in an ImmutableMultiset<Address>. Invalidate the entire cache any time a
tx set change occurs, by attaching a WalletChangeEventListener to the
wallet (using a direct executor for immediate effect).
This is to fix a quadratic time bug in DepositView, which uses the count
to determine if a given address in the BTC wallet is used/unused.
Make the WalletService.walletEventListener field private and add it via
a protected method defined in the base class, addListenersToWallet(), so
that the setup code in the two subclasses (Bsq|Btc)WalletService can be
deduplicated and more easily kept in sync with the listener removal code
in WalletService.shutDown().
Also remove some unnecessary deprecation warning suppressions.
The general rule is limit calls that change p2p data to 1/minute,
others to 1/second. An exception is made to set/remove wallet password
methods (1/5s), due to the latency of writing wallet changes to disk.
This change may affect api testing in the future. If that happens,
further changes to the call rate metering interceptor may be made to loosen
the constraints when running in regtest/dev mode.
- trims whitespace from numeric input fields before parsing
- adds percentage display of the tx fee
- validates that the tx fee percentage is not higher than 10%
- trims whitespace from numeric input fields before parsing
- adds percentage display of the tx fee
- validates that the tx fee percentage is not higher than 10%
Avoid name clashes between the Json RPC client DTOs & the corresponding
raw (un-parsed) DAO state entities. Also prepend the other DTO classes
with 'Dto' for consistency.
Add missing 'connections_(in|out)' JSON properties to NetworkInfo that
came with the recent 0.21.0 release of Bitcoin Core. Also ensure that
unrecognised JSON properties are ignored, so that future changes to the
RPC API are less likely to break our client.
Also, for the benefit of the tests, change the JSON property order of
RawInput to better match observed 'getblock' responses. (It appears that
in 0.21.0, extra "txinwitness" fields have started appearing in coinbase
inputs, which may be a bug.)
Since extraction of segwit pubkeys technically represents a hard fork,
activate it by block height in the same way as the fork defined in
TxOutputParser, instead of relying on the absence of premature segwit
BSQ inputs outside of a blacklist. This also means we no longer need to
exclude all but the first tx input from segwit pubkey extraction to
maintain backwards compatibility, which is a little safer and consistent
with the original behaviour of extracting every available P2PKH pubkey.
Provisionally activate this (2nd) DAO hard fork at block height 672646,
which should be 6 weeks from now, just under 5 weeks from the planned
1.5.5 release on 2021/01/27. (Block 1906689 for testnet - 2 weeks from
now assuming an average block time of 10 minutes, but it's erratic.)
Make a 'getnetworkinfo' RPC call to bitcoind immediately upon startup,
to check that the node is up (and throw a ConnectException to ensure
that the user is presented with an appropriate warning popup otherwise).
Log a warning if the node version is outside the 0.18.0 - 0.20.1 range.
Additionally, call 'getbestblockhash' to check that the chain tip is not
stale (> 6 hours old). As part of this, make sure the 'getblock' RPC
call works correctly with verbosity < 2, by fixing JSON deserialisation
of the response when the block or txs are in summary (hex string) form.
(These version & health checks are almost identical to the ones done by
the original btcd-cli4j library during RPC client startup.)
Provide a 'NetworkInfo' DTO class (with associated nested DTO classes),
returned by the 'getnetworkinfo' RPC method call to bitcoind. This will
be used during startup of RpcService to determine if Bitcoin Core is
available and which version it is using. Add a unit test to round-trip a
sample NetworkInfo JSON response.
Also add the missing 'getbestblockhash' RPC method, which will be needed
by RpcService to determine the Bitcoin Core node health.
Selectively disable pubkey extraction from segwit inputs of a particular
tx at block height 660384 (2020-12-07), which spends spuriously created
segwit BSQ (later burned), to prevent a change in the DAO state hashes
from that point.
(Since a tx with a given ID can only appear on one chain, a fixed global
exclusion list of IDs should not cause any issues on testnet/regtest
versus mainnet. This is simpler than conditioning by block height.)
Prevent intermittent test failures, caused by a race between checking
whether the mock socket is closed upon accepting a new connection and
setting 'socketClosed' to true during shutdown. Waiting to accept and
then checking the flag needs to be done in a synchronized block.
Factor out shared construction logic to a new 'getBlockFromRawDtoBlock'
method in RpcService. Also add some 'NOPMD' comments in an attempt to
suppress unfixable Codacy warnings about qualified imports.
Factor out a new RpcService.extractPubKeyAsHex method, to take public
keys from the inputs of the raw transactions returned by the RPC client,
when building TxInput objects to incorporate into the DAO state. Enhance
the method to additionally support segwit (P2WPKH & P2SH-P2WPKH) inputs
(but only the first input for backwards compatibility - see code
comment). Also fix a bug when handling non-SIGHASH_ALL input signatures.
This will allow segwit BSQ to be used in proof-of-burn and issuance txs,
which need a public key associated with the tx to establish ownership of
it, when signing messages with a proof-of-burn or staking merit awarded
from a compensation issuance, respectively.
Also add unit tests for the factored-out method and add a missing RawTx
toString() method, to aid debugging the TxInput fields within the
processed block returned by RpcService.
Migrate RpcService over to the new block notification daemon and RPC
client based on jsonrpc4j. Drop in own DTO classes in place of the ones
defined by btcd-cli4j and rename requestBtcBlock & addNewBtcBlockHandler
to requestDtoBlock & addNewDtoBlockHandler respectively.
Also remove now redundant filtering from the logback config and update
grade-witness.
Wrap any exception that occurs during socket IO or within the supplied
BlockListener with a new 'BlockNotificationException'. This brings the
exception handling more in line with that of the old BtcdDaemonImpl and
makes it easier to match them downstream in FullNode.handleError.