-
Notifications
You must be signed in to change notification settings - Fork 143
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
Trusted state completer #946
Conversation
Codecov Report
@@ Coverage Diff @@
## main #946 +/- ##
==========================================
+ Coverage 87.98% 88.13% +0.14%
==========================================
Files 269 276 +7
Lines 24872 25270 +398
==========================================
+ Hits 21883 22271 +388
- Misses 1531 1540 +9
- Partials 1458 1459 +1
|
5186eac
to
6354245
Compare
772b1f6
to
ed9b1f8
Compare
@planetarium/libplanet Please review this. |
continue; | ||
} | ||
|
||
BlockChain.Store.SetBlockStates(blockStates.BlockHash, blockStates.States); |
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.
Is it fine without any of the mutex?
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.
Rather it does not work (gets dead-locked) if we try to lock the BlockChain._rwlock
here, because BlockChain<T>.GetState()
/GetBalance()
methods guarantee their stateCompleter
to be called only in the read lock:
libplanet/Libplanet/Blockchain/BlockChain.cs
Lines 1680 to 1702 in ed9b1f8
_rwlock.EnterUpgradeableReadLock(); | |
try | |
{ | |
stateReference = Store.LookupStateReference(Id, key, block); | |
if (stateReference is null) | |
{ | |
return null; | |
} | |
HashDigest<SHA256> hashValue = stateReference.Item1; | |
IImmutableDictionary<string, IValue> blockStates = Store.GetBlockStates(hashValue); | |
if (blockStates is null) | |
{ | |
return rawStateCompleter(this, hashValue); | |
} | |
return blockStates.TryGetValue(key, out IValue state) ? state : null; | |
} | |
finally | |
{ | |
_rwlock.ExitUpgradeableReadLock(); | |
} |
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.
I see... then it seems that we should upgrade _rwlock
before calling rawStateCompleter
in BlockChain<T>.GetRawState()
.
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.
Not all state completers update the blockchain, but only Recalculate
completers do. Those implementations have already entered the write lock by themselves.
libplanet/Libplanet/Blockchain/BlockChain.cs
Lines 1638 to 1647 in ed9b1f8
_rwlock.EnterWriteLock(); | |
try | |
{ | |
SetStates(block, evaluations, buildStateReferences: false); | |
} | |
finally | |
{ | |
_rwlock.ExitWriteLock(); | |
} |
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.
Then, shouldn't these state completers upgrade _rwlocks
? (like Recalculate
)
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.
@longfin I'm going to address this problem in the next separated pull request!
{ | ||
StateCompleter = (blockChain, blockHash, address) => | ||
{ | ||
FillTrustedBlockStates(blockHash).Wait(cancellationToken); |
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.
It can be a trouble if StateCompleter
is called in an async
method... but it doesn't seem translatable to async
because StateCompleter
and related features are all synchronous. 🤔
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.
That's what I'd grappled with, but I gave up and decided to request for comments about this problem…
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.
@longfin I'm going to address this problem in the next separated pull request!
094e483
to
f0e715a
Compare
@planetarium/libplanet Please review this again, folks! |
planetarium#946 (comment) [changelog skip]
This patch is continued from the previous patch #934 and addresses the idea sketched in the issue #929.
However, in general I became to believe this approach is not appropriate. Here I elaborate:
Rendering and unrendering whole actions between two tips on reorg anyway requires all states of every step, and it means the idea of cherry-picking only recent states is pointless for this case.
Even if we decide to fetch (trust) all states from peers for every step between two tips on reorg, it rather takes longer time than recalculating all states.
We are slowly moving towards chain-interior-states (from chain-exterior-states, the status quo): Inserting a state hash into the
BlockHeader
#931,PreEvaluationHash
onBlock<T>
andBlockHeader
#935, and Introduce Merkle Patricia Trie #939. Eventually, we won't need any trust for reusing states calculated by peers, after all.Hence, although I prepared this patch for a quite long time, I doubt this works well for the problem addressed by the issue #929. 🤔