Most often we only need to read them and it doesn't require copying. Make an
explicit copy (and copy only things we need!) where needed.
After the recent neo-vm tests update our vm package testing time jumped to
~12s, with this change it's now more like ~8s.
Inspired by neo-project/neo-vm#352. We can't directly compare slices, so we're
better optimize things we already have. At the same time this code would
behave a bit different if A is to call B and then B is call A and then some
pointer from the first A invocation is to be compared with a pointer from the
second A invocation. Not sure it really matters.
Now we have VerifyTx() and PoolTx() APIs that either verify transaction in
isolation or verify it against the mempool (either the primary one or the one
given) and then add it there. There is no possibility to check against the
mempool, but not add a transaction to it, but I doubt we really need it.
It allows to remove some duplication between old PoolTx and verifyTx where
they both tried to check transaction against mempool (verifying first and then
adding it). It also saves us utility token balance check because it's done by
the mempool anyway and we no longer need to do that explicitly in verifyTx.
It makes AddBlock() and verifyBlock() transaction's checks more correct,
because previously they could miss that even though sender S has enough
balance to pay for A, B or C, he can't pay for all of them.
Caveats:
* consensus is running concurrently to other processes, so things could
change while verifyBlock() is iterating over transactions, this will be
mitigated in subsequent commits
Improves TPS value for single node by at least 11%.
Fixes#667, fixes#668.
It's cached in dbft for a view anyway, so there is no big difference here
from security POV. Lets us squeeze yet another 4% TPS improvement.
Make the system fail if unable to decrypt the key along the way, which is a
part of #1312.
New transactions are added to the chain with blocks. If there is no
transaction X at height N in DAO, it could only be added with block N+1, so
it has to be present there. Therefore we can replace `dao.HasTransaction()`
check with a search through in-block transactions. HasTransaction() is nasty
in that it may add useless load the DB and this code is being run with a big
Blockchain lock held, so we don't want to be delayed here at all.
Improves single-node TPS by ~2%.
The end effect is almost as if `VerifyTransactions: false` was set in the
config, but without actually compromising the guarantees provided by it.
It almost doubles performance for single-mode benchmarks and makes block
processing smoother (more smaller blocks are being produced).