Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ private void initializeStorage() {

Hash32 initialStateRoot = spec.hash_tree_root(initialState);
BeaconBlock genesis = initialGenesis.withStateRoot(initialStateRoot);
Hash32 genesisRoot = spec.signed_root(genesis);
Hash32 genesisRoot = spec.signing_root(genesis);
BeaconTuple tuple = BeaconTuple.of(genesis, initialState);

tupleStorage.put(tuple);
Expand Down Expand Up @@ -120,7 +120,7 @@ public synchronized boolean insert(BeaconBlock block) {
blockVerifier.verify(block, preBlockState);
if (!blockVerification.isPassed()) {
logger.warn("Block verification failed: " + blockVerification + ": " +
block.toString(spec.getConstants(), parentState.getGenesisTime(), spec::signed_root));
block.toString(spec.getConstants(), parentState.getGenesisTime(), spec::signing_root));
return false;
}

Expand Down Expand Up @@ -151,7 +151,7 @@ public synchronized boolean insert(BeaconBlock block) {
.toString(
spec.getConstants(),
newTuple.getState().getGenesisTime(),
spec::signed_root),
spec::signing_root),
String.format("%.3f", ((double) total) / 1_000_000_000d));

return true;
Expand All @@ -165,13 +165,13 @@ public BeaconTuple getRecentlyProcessed() {
private void updateFinality(BeaconState previous, BeaconState current) {
if (previous.getFinalizedEpoch().less(current.getFinalizedEpoch())) {
Hash32 finalizedRoot =
spec.get_block_root(
spec.get_block_root_at_slot(
current, spec.get_epoch_start_slot(current.getFinalizedEpoch()));
chainStorage.getFinalizedStorage().set(finalizedRoot);
}
if (previous.getCurrentJustifiedEpoch().less(current.getCurrentJustifiedEpoch())) {
Hash32 justifiedRoot =
spec.get_block_root(
spec.get_block_root_at_slot(
current, spec.get_epoch_start_slot(current.getCurrentJustifiedEpoch()));
chainStorage.getJustifiedStorage().set(justifiedRoot);
}
Expand All @@ -186,7 +186,7 @@ private BeaconStateEx pullParentState(BeaconBlock block) {
}

private boolean exist(BeaconBlock block) {
Hash32 blockHash = spec.signed_root(block);
Hash32 blockHash = spec.signing_root(block);
return chainStorage.getBlockStorage().get(blockHash).isPresent();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,15 @@ public String toString(@Nullable BeaconChainSpec spec) {
String committee = "";
if (spec != null) {
committee = " Proposer/Committee: "
+ spec.get_beacon_proposer_index(getLatestSlotState(), getLatestSlotState().getSlot())
+ spec.get_beacon_proposer_index(getLatestSlotState())
+ " "
+ spec.get_crosslink_committees_at_slot(
getLatestSlotState(), getLatestSlotState().getSlot()).get(0).getCommittee()
+ " ";
}

return "ObservableBeaconState[head="
+ (spec != null ? spec.signed_root(head).toStringShort() : head.toString(null ,null, null))
+ (spec != null ? spec.signing_root(head).toStringShort() : head.toString(null ,null, null))
+ ", latestState: "
+ committee
+ latestSlotState.toStringShort(spec == null ? null : spec.getConstants())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
package org.ethereum.beacon.chain.observer;

import java.time.Duration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import org.ethereum.beacon.chain.BeaconChainHead;
import org.ethereum.beacon.chain.BeaconTuple;
import org.ethereum.beacon.chain.BeaconTupleDetails;
import org.ethereum.beacon.chain.LMDGhostHeadFunction;
import org.ethereum.beacon.chain.storage.BeaconChainStorage;
import org.ethereum.beacon.chain.storage.BeaconTupleStorage;
import org.ethereum.beacon.consensus.BeaconChainSpec;
import org.ethereum.beacon.consensus.BeaconStateEx;
import org.ethereum.beacon.consensus.HeadFunction;
import org.ethereum.beacon.consensus.BeaconChainSpec;
import org.ethereum.beacon.consensus.transition.EmptySlotTransition;
import org.ethereum.beacon.core.BeaconBlock;
import org.ethereum.beacon.core.BeaconState;
import org.ethereum.beacon.core.operations.Attestation;
import org.ethereum.beacon.core.state.PendingAttestation;
import org.ethereum.beacon.core.types.BLSPubkey;
import org.ethereum.beacon.core.types.EpochNumber;
import org.ethereum.beacon.core.types.SlotNumber;
import org.ethereum.beacon.core.types.ValidatorIndex;
import org.ethereum.beacon.schedulers.Scheduler;
Expand All @@ -25,15 +34,7 @@
import org.javatuples.Pair;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;

import java.time.Duration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import tech.pegasys.artemis.util.uint.UInt64s;

public class ObservableStateProcessorImpl implements ObservableStateProcessor {
private static final int MAX_TUPLE_CACHE_SIZE = 256;
Expand All @@ -53,7 +54,7 @@ public class ObservableStateProcessorImpl implements ObservableStateProcessor {
private Cache<BeaconBlock, BeaconTupleDetails> tupleDetails = new LRUCache<>(MAX_TUPLE_CACHE_SIZE);

private final List<Attestation> attestationBuffer = new ArrayList<>();
private final Map<Pair<BLSPubkey, SlotNumber>, Attestation> attestationCache = new HashMap<>();
private final Map<Pair<BLSPubkey, EpochNumber>, Attestation> attestationCache = new HashMap<>();
private final Schedulers schedulers;

private final SimpleProcessor<BeaconChainHead> headStream;
Expand Down Expand Up @@ -100,17 +101,16 @@ private void runTaskInSeparateThread(Runnable task) {
}

private void onNewSlot(SlotNumber newSlot) {
// From spec: Verify that attestation.data.slot <= state.slot - MIN_ATTESTATION_INCLUSION_DELAY
// < attestation.data.slot + SLOTS_PER_EPOCH
// state.slot - MIN_ATTESTATION_INCLUSION_DELAY < attestation.data.slot + SLOTS_PER_EPOCH
// state.slot - MIN_ATTESTATION_INCLUSION_DELAY - SLOTS_PER_EPOCH < attestation.data.slot
SlotNumber slotMinimum =
newSlot
.minus(spec.getConstants().getSlotsPerEpoch())
.minus(spec.getConstants().getMinAttestationInclusionDelay());
/* From spec:
attestation_slot = get_attestation_slot(state, attestation)
assert attestation_slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= attestation_slot + SLOTS_PER_EPOCH */
SlotNumber slotMinimum = newSlot
.minusSat(spec.getConstants().getSlotsPerEpoch())
.minusSat(spec.getConstants().getMinAttestationInclusionDelay());
EpochNumber epochMinimum = spec.slot_to_epoch(slotMinimum);
runTaskInSeparateThread(
() -> {
purgeAttestations(slotMinimum);
purgeAttestations(epochMinimum);
newSlot(newSlot);
});
}
Expand All @@ -119,11 +119,11 @@ private void doHardWork() {
if (latestState == null) {
return;
}
List<Attestation> attestations = drainAttestations(latestState.getSlot());
List<Attestation> attestations = drainAttestations(spec.get_current_epoch(latestState));
for (Attestation attestation : attestations) {

List<ValidatorIndex> participants =
spec.get_attestation_participants(
spec.get_attesting_indices(
latestState, attestation.getData(), attestation.getAggregationBitfield());

List<BLSPubkey> pubKeys = spec.mapIndicesToPubKeys(latestState, participants);
Expand All @@ -135,19 +135,19 @@ private void doHardWork() {
}

private synchronized void addValidatorAttestation(BLSPubkey pubKey, Attestation attestation) {
attestationCache.put(Pair.with(pubKey, attestation.getData().getSlot()), attestation);
attestationCache.put(Pair.with(pubKey, attestation.getData().getTargetEpoch()), attestation);
}

private synchronized void onNewAttestation(Attestation attestation) {
attestationBuffer.add(attestation);
}

private synchronized List<Attestation> drainAttestations(SlotNumber uptoSlotInclusive) {
private synchronized List<Attestation> drainAttestations(EpochNumber upToEpochInclusive) {
List<Attestation> ret = new ArrayList<>();
Iterator<Attestation> it = attestationBuffer.iterator();
while (it.hasNext()) {
Attestation att = it.next();
if (att.getData().getSlot().lessEqual(uptoSlotInclusive)) {
if (att.getData().getTargetEpoch().lessEqual(upToEpochInclusive)) {
ret.add(att);
it.remove();
}
Expand All @@ -171,27 +171,27 @@ private void addAttestationsFromState(BeaconState beaconState) {
pendingAttestations.addAll(beaconState.getPreviousEpochAttestations().listCopy());
for (PendingAttestation pendingAttestation : pendingAttestations) {
List<ValidatorIndex> participants =
spec.get_attestation_participants(
spec.get_attesting_indices(
beaconState,
pendingAttestation.getData(),
pendingAttestation.getAggregationBitfield());
List<BLSPubkey> pubKeys = spec.mapIndicesToPubKeys(beaconState, participants);
SlotNumber slot = pendingAttestation.getData().getSlot();
EpochNumber targetEpoch = pendingAttestation.getData().getTargetEpoch();
pubKeys.forEach(
pubKey -> {
removeValidatorAttestation(pubKey, slot);
removeValidatorAttestation(pubKey, targetEpoch);
});
}
}

private synchronized void removeValidatorAttestation(BLSPubkey pubkey, SlotNumber slot) {
attestationCache.remove(Pair.with(pubkey, slot));
private synchronized void removeValidatorAttestation(BLSPubkey pubkey, EpochNumber epoch) {
attestationCache.remove(Pair.with(pubkey, epoch));
}

/** Purges all entries for slot and before */
private synchronized void purgeAttestations(SlotNumber slot) {
/** Purges all entries for epoch and before */
private synchronized void purgeAttestations(EpochNumber targetEpoch) {
attestationCache.entrySet()
.removeIf(entry -> entry.getValue().getData().getSlot().lessEqual(slot));
.removeIf(entry -> entry.getValue().getData().getTargetEpoch().less(targetEpoch));
}

private synchronized Map<BLSPubkey, List<Attestation>> copyAttestationCache() {
Expand Down Expand Up @@ -228,7 +228,7 @@ private void newSlot(SlotNumber newSlot) {
private void updateCurrentObservableState(BeaconTupleDetails head, SlotNumber slot) {
assert slot.greaterEqual(head.getBlock().getSlot());

PendingOperations pendingOperations = new PendingOperationsState(copyAttestationCache());
PendingOperations pendingOperations = new PendingOperationsState(spec, copyAttestationCache());
if (slot.greater(head.getBlock().getSlot())) {
BeaconStateEx stateUponASlot = emptySlotTransition.apply(head.getFinalState(), slot);
latestState = stateUponASlot;
Expand All @@ -253,7 +253,7 @@ private void updateCurrentObservableState(BeaconTupleDetails head, SlotNumber sl
}

private void updateHead() {
PendingOperations pendingOperations = new PendingOperationsState(copyAttestationCache());
PendingOperations pendingOperations = new PendingOperationsState(spec, copyAttestationCache());
BeaconBlock newHead =
headFunction.getHead(
validatorRecord -> pendingOperations.getLatestAttestation(validatorRecord.getPubKey()));
Expand All @@ -266,7 +266,7 @@ private void updateHead() {
(head) -> {
BeaconTuple newHeadTuple =
tupleStorage
.get(spec.signed_root(head))
.get(spec.signing_root(head))
.orElseThrow(
() -> new IllegalStateException("Beacon tuple not found for new head "));
return new BeaconTupleDetails(newHeadTuple);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.List;
import java.util.Optional;
import org.ethereum.beacon.core.BeaconState;
import org.ethereum.beacon.core.operations.Attestation;
import org.ethereum.beacon.core.operations.ProposerSlashing;
import org.ethereum.beacon.core.operations.Transfer;
Expand All @@ -23,7 +24,7 @@ public interface PendingOperations {
List<AttesterSlashing> peekAttesterSlashings(int maxCount);

List<Attestation> peekAggregatedAttestations(
int maxCount, SlotNumber minSlotExclusive, SlotNumber maxSlotInclusive);
int maxCount, BeaconState state, SlotNumber minSlotExclusive, SlotNumber maxSlotInclusive);

List<VoluntaryExit> peekExits(int maxCount);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import org.ethereum.beacon.consensus.BeaconChainSpec;
import org.ethereum.beacon.core.BeaconState;
import org.ethereum.beacon.core.operations.Attestation;
import org.ethereum.beacon.core.operations.ProposerSlashing;
import org.ethereum.beacon.core.operations.Transfer;
import org.ethereum.beacon.core.operations.VoluntaryExit;
import org.ethereum.beacon.core.operations.ProposerSlashing;
import org.ethereum.beacon.core.operations.attestation.AttestationData;
import org.ethereum.beacon.core.operations.slashing.AttesterSlashing;
import org.ethereum.beacon.core.types.BLSPubkey;
Expand All @@ -24,15 +26,20 @@
public class PendingOperationsState implements PendingOperations {

Map<BLSPubkey, List<Attestation>> attestations;
private final BeaconChainSpec spec;

public PendingOperationsState(Map<BLSPubkey, List<Attestation>> attestations) {
public PendingOperationsState(
BeaconChainSpec spec, Map<BLSPubkey, List<Attestation>> attestations) {
this.spec = spec;
this.attestations = attestations;
}

@Override
public Optional<Attestation> getLatestAttestation(BLSPubkey pubKey) {
return Optional.ofNullable(attestations.get(pubKey))
.map(atts -> Collections.max(atts, Comparator.comparing(att -> att.getData().getSlot())));
.map(
atts ->
Collections.max(atts, Comparator.comparing(att -> att.getData().getTargetEpoch())));
}

@Override
Expand All @@ -52,18 +59,22 @@ public List<AttesterSlashing> peekAttesterSlashings(int maxCount) {

@Override
public List<Attestation> peekAggregatedAttestations(
int maxCount, SlotNumber minSlotExclusive, SlotNumber maxSlotInclusive) {
int maxCount, BeaconState state, SlotNumber minSlotExclusive, SlotNumber maxSlotInclusive) {

Map<AttestationData, List<Attestation>> attestationsBySlot =
getAttestations()
.stream()
.filter(attestation -> attestation.getData().getSlot().greater(minSlotExclusive))
.filter(attestation -> attestation.getData().getSlot().lessEqual(maxSlotInclusive))
getAttestations().stream()
.filter(attestation -> {
SlotNumber attestationSlot =
spec.get_attestation_slot(state, attestation.getData());
// minExclusive < attestationSlot <= maxSlotInclusive
return minSlotExclusive.less(attestationSlot)
&& attestationSlot.lessEqual(maxSlotInclusive);
})
.collect(groupingBy(Attestation::getData));
return attestationsBySlot
.entrySet()
.stream()
.sorted(Comparator.comparing(e -> e.getKey().getSlot()))
.sorted(Comparator.comparing(e -> e.getKey().getTargetEpoch()))
.limit(maxCount)
.map(entry -> aggregateAttestations(entry.getValue()))
.collect(Collectors.toList());
Expand All @@ -83,7 +94,7 @@ private Attestation aggregateAttestations(List<Attestation> attestations) {
BLS381.Signature aggregatedSignature =
BLS381.Signature.aggregate(
attestations.stream()
.map(Attestation::getAggregateSignature)
.map(Attestation::getSignature)
.map(BLS381.Signature::create)
.collect(Collectors.toList()));
BLSSignature aggSign = BLSSignature.wrap(aggregatedSignature.getEncoded());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import java.util.Collections;
import java.util.stream.IntStream;
import org.ethereum.beacon.chain.storage.BeaconChainStorage;
import org.ethereum.beacon.chain.storage.BeaconChainStorageFactory;
import org.ethereum.beacon.chain.storage.impl.SSZBeaconChainStorageFactory;
import org.ethereum.beacon.chain.storage.impl.SerializerFactory;
import org.ethereum.beacon.consensus.BeaconChainSpec;
Expand All @@ -22,8 +21,8 @@
import org.ethereum.beacon.core.BeaconBlock;
import org.ethereum.beacon.core.BeaconBlockBody;
import org.ethereum.beacon.core.BeaconState;
import org.ethereum.beacon.core.spec.SpecConstants;
import org.ethereum.beacon.core.state.Eth1Data;
import org.ethereum.beacon.core.types.BLSSignature;
import org.ethereum.beacon.core.types.Time;
import org.ethereum.beacon.db.Database;
import org.ethereum.beacon.pow.DepositContract.ChainStart;
Expand Down Expand Up @@ -69,10 +68,10 @@ private BeaconBlock createBlock(
BeaconBlock block =
new BeaconBlock(
spec.get_current_slot(parent.getState(), currentTime),
spec.signed_root(parent.getBlock()),
spec.signing_root(parent.getBlock()),
Hash32.ZERO,
BeaconBlockBody.EMPTY,
spec.getConstants().getEmptySignature());
BLSSignature.ZERO);
BeaconState state = perSlotTransition.apply(new BeaconStateExImpl(parent.getState()));

return block.withStateRoot(spec.hash_tree_root(state));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class BeaconBlockStorageTest {
private BeaconBlockStorage create(BeaconChainSpec spec) {
return BeaconBlockStorageImpl.create(
Database.inMemoryDB(),
ObjectHasher.createSSZOverKeccak256(spec.getConstants()),
ObjectHasher.createSSZOverSHA256(spec.getConstants()),
SerializerFactory.createSSZ(spec.getConstants()));
}

Expand Down
Loading