New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hash Cache #8259
Hash Cache #8259
Conversation
95f8516
to
c2ea4dd
Compare
This one is hopefully merged for versions with segwit defined on mainnet |
bool TrySet(uint256 txId, const CachedHashes& hashes) | ||
{ | ||
LOCK(cs); | ||
if(map.count(txId)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could avoid two look ups (IIRC) by comparing the size of the container before and after instead.
Aka:
auto sizeBefore = map.size();
map.insert(txId, hashes);
return map.size() != sizeBefore;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I don't think I really need TrySet to return a bool.
hash caches?, had me confused for a second haha utACK c2ea4dd |
class CachedHashes | ||
{ | ||
public: | ||
uint256 hashPrevouts,hashSequence,hashOutputs; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
trivial: maybe spacing between names?
utACK dc188d8 |
@@ -1110,35 +1110,46 @@ class CTransactionSignatureSerializer { | |||
|
|||
} // anon namespace | |||
|
|||
uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion) | |||
uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, CachedHashes* cache) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps here we can do the same trick we did with the script/sigcache to keep script/interpreter simpler and more reusable.
ping @sipa
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or maybe move SignatureHash to BaseSignatureChecker. Just brainstorming.
Assume a transaction has many signatures. One is SIGHASH_SINGLE, all the others are SIGHASH_ALL | SIGHASH_ANYONECANPAY. The first computes and stores hashPrevouts. All the others will compute hashOutputs. However, after the first call, all TrySets will not do anything, as there is already a result in the cache, so it gets computed over and over again. I think CachedHashes needs a Merge method like this:
which can then be called from TrySet (instead of insert, use |
That's not true, I would be calculating the three hashes at the same time during the SIGHASH_SINGLE. I prefer not doing a merge. Without a merge my lock only have to protect the internal map as CachedHashes instances are read only. If we calculate the mid states lazily, I also need to be careful about locking at the CachedHashes instance level. |
@NicolasDorier Oh, I see. I agree that the current code is fine in that case. I don't understand the argument about the lock. The Merge function would also grab the lock, and be the only code that touches the map. |
@sipa The Merge function as you did here can't grab the lock, because the lock is at the cache map level, not at the CachedHashes instance level. But basically, if doing that way, I would need to grab the lock of the map around the Merge, as well as around any hash read of the HashedCaches instance. (so one can't read and call merge on the HashedCaches at the same time) |
Closing this one in favor of #8422 which calculate hashes lazily. |
Some notes about the implementation:
Befinits are:
This commit is only for having a cache that is simple to review and understand. It is probably possible to fix the two first points above, but the code overhead is not worth it when our goal is only to fix the O(n²) issue.
(rebased version of sipa#70)