-
-
Notifications
You must be signed in to change notification settings - Fork 310
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
EIP-6110 in-protocol deposits epic #5366
Comments
BackgroundThe current interface of the pubkey cache is interface PubkeyCache {
/** When processing signed objects must resolve validator indexes into a representation of the pubkey
optimized for fast aggregation */
getPubkeyForAggregation(index: ValidatorIndex): bls.PublicKey;
/** `process_deposit` requires to efficiently lookup if a pubkey is known in the state or not */
getPubkeyIndex(pubkey: bytes): ValidatorIndex | null;
/** Register new pubkey to cache. May be done when processing deposit or latter */
addPubkey(pubkey: bytes, index: ValidatorIndex): void;
} That API is currently implemented with two data structures which are globally shared on all states type Index2PubkeyCache = PublicKey[];
type PubkeyIndexMap = Map<PubkeyHex, ValidatorIndex>(); Split cacheAs @g11tech mentions we must have a cache that's fork aware. We should use the So attach to every state this two datastructures that are cloned on each state clone and can be safely mutated on block processing
The mutliplex on both caches function getPubkeyForAggregation(index: ValidatorIndex): bls.PublicKey {
if (index < latestFinalizedValidatorsLen) {
// Lookup global cache
// - Should cover +99% of cases. Random access on fast Array
return globalPubkeyCache[index];
} else {
// Lookup state's local cache
// - Unlikely unless long non-finality. Slower access on immutable.List
if (unfinalizedPubkeyCache[index] == null) {
// Prime cache reading into the state.validators[index].pubkey
// To prevent deserializing pubkey twice, keep global `unfinalizedPubkeyMap = Map<PubkeyHex, PublicKey>`
// Deserialization may be done proactively if unfinalized validators become active
primeUnfinalizedPubkeyCache(index);
}
return unfinalizedPubkeyCache[index];
}
} function getPubkeyIndex(pubkey: bytes): ValidatorIndex | null {
// Lookup global cache
return globalPubkeyIndexMap.get(pubkey)
// Then lookup local cache
// - Note now for new deposits both caches will be lookup
|| unfinalizedPubkeyIndexMap.get(pubkey);
} Regarding cache insertion, we must ensure that each pubkey is only deserialized once, since those representations are memory heavy. function addPubkey(pubkey: bytes, index: ValidatorIndex): void {
unfinalizedPubkeyCache.set(index, null); // lazy cache, prime latter
unfinalizedPubkeyIndexMap.set(pubkey, index);
} Re-use indexes
|
I think we can make |
I have dug into the current use of There is also a case where I believe there is no need to have the multiplex in |
aha very nice analysis @naviechan
what about
i suggest to keep the original approach proposed, where we prime them in a lazy fashion. |
Having a fork aware auto-pruned index2pubkey for non-finalized pubkeys is a complexity we should avoid if not necessary. To verify signatures the fallback can be:
awfully slow, but covers the case. We should have WARN logs if that codepath happens For pubkey2index we 100% need the un-finalized cache |
makes sense, so the we can encapsulate this away in (or put it in cache as well depending upon the optional flags to cache, but all that can be done later on based on usage requirements) |
I realized this is a bold claim without any supporting evidence. Many thanks to @dapplion for suggestions and comments |
In the case of long non-finality:
|
yes no need i think 👍 , also no need for |
The EIP aims to bring deposit mechanism in the beacon chain. Currently the deposits and fetched and processed wiith a sufficient lag (12 hrs) that sort of effectively rule out any change of re-org in terms of processing deposits. With now the proposed deposit receipt being the first order citizen of the beacon network and a beacon node bundle and pack them in a block to add them into canonical chain (like other messages like exit, bls changes etc)
Following would be the tracker items:
However apart from these routine tasks, lodestar would need to refactor and handle its pubkey <> index map which is currently part of EpochContext which is a global object. Currently since deposit logs from EL are processed with such a big log, its very deterministic the order in which deposits would be processed and packed in the blocks and hence gets assigned indexes in EpochContext without any worries.
But with moving the deposit receipt processing in the beacon, this determinism goes away as now the indexes will now depend on the block receipt packing, more precisely varying between the forks. This leads to the precursor refactoring task.
tip
node in the forkchoice protoarray (i.e no children) have an additionalforkMap
which is basically obtained by applying the receipts in order of theunfinalized
blocks added in the fork.tip
map is updated and assigned to the new tipPS: still wip and pending discussions
cc @dapplion @wemeetagain
The text was updated successfully, but these errors were encountered: