Skip to content
This repository has been archived by the owner on Feb 19, 2024. It is now read-only.

Commit

Permalink
Return real values for validator owners' stake and allowsDelegation flag
Browse files Browse the repository at this point in the history
  • Loading branch information
siy committed Jun 22, 2021
1 parent 08ddda7 commit a43fe68
Show file tree
Hide file tree
Showing 7 changed files with 165 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.radixdlt.identifiers.REAddr;
import org.json.JSONObject;

import com.radixdlt.statecomputer.ValidatorDetails;
import com.radixdlt.utils.UInt256;

import static com.radixdlt.api.JsonRpcUtil.jsonObject;
Expand Down Expand Up @@ -74,6 +75,19 @@ public static ValidatorInfoDetails create(
return new ValidatorInfoDetails(validator, owner, name, infoUrl, totalStake, ownerStake, externalStakesAllowed);
}

public static ValidatorInfoDetails create(ValidatorDetails details) {
return create(
details.getKey(),
details.getOwner(),
details.getName(),
details.getUrl(),
details.getStake(),
details.getOwnerStake(),
details.allowsDelegation()
);
}


public String getValidatorAddress() {
return ValidatorAddress.of(validator);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
import com.radixdlt.identifiers.ValidatorAddress;
import com.radixdlt.statecomputer.LedgerAndBFTProof;
import com.radixdlt.statecomputer.StakedValidators;
import com.radixdlt.statecomputer.ValidatorDetails;
import com.radixdlt.utils.UInt256;
import com.radixdlt.utils.functional.FunctionalUtils;
import com.radixdlt.utils.functional.Result;
import com.radixdlt.utils.functional.Result.Mapper2;
Expand All @@ -50,8 +48,7 @@ public Mapper2<Optional<ECPublicKey>, List<ValidatorInfoDetails>> getValidators(
int size, Optional<ECPublicKey> cursor
) {
var validators = radixEngine.getComputedState(StakedValidators.class);

var result = validators.map(this::fillDetails);
var result = validators.map(ValidatorInfoDetails::create);
result.sort(Comparator.comparing(ValidatorInfoDetails::getTotalStake).reversed());

var paged = cursor
Expand All @@ -66,8 +63,9 @@ public Mapper2<Optional<ECPublicKey>, List<ValidatorInfoDetails>> getValidators(

public List<ValidatorInfoDetails> getAllValidators() {
var validators = radixEngine.getComputedState(StakedValidators.class);
var result = validators.map(this::fillDetails);
var result = validators.map(ValidatorInfoDetails::create);
result.sort(Comparator.comparing(ValidatorInfoDetails::getTotalStake).reversed());

return result;
}

Expand All @@ -80,19 +78,8 @@ public Result<ValidatorInfoDetails> getValidator(ECPublicKey validatorPublicKey)

return Result.fromOptional(
UNKNOWN_VALIDATOR.with(ValidatorAddress.of(validatorPublicKey)),
validators.mapSingle(validatorPublicKey, details -> fillDetails(validatorPublicKey, details))
validators.mapSingle(validatorPublicKey, ValidatorInfoDetails::create)
);
}

private ValidatorInfoDetails fillDetails(ECPublicKey validatorKey, ValidatorDetails details) {
return ValidatorInfoDetails.create(
validatorKey,
details.getOwner(),
details.getName(),
details.getUrl(),
details.getStake(),
UInt256.ZERO,
true
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,13 @@
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.radixdlt.utils.functional.FunctionalUtils.removeKey;
import static com.radixdlt.utils.functional.FunctionalUtils.replaceEntry;

import static java.util.Optional.ofNullable;

/**
* Wrapper class for registered validators
Expand All @@ -47,10 +50,12 @@ public final class StakedValidators {

private final Map<ECPublicKey, UInt256> stake;
private final Map<ECPublicKey, REAddr> owners;
private final Map<ECPublicKey, Boolean> delegationFlags;
private final Set<ValidatorParticle> validatorParticles;
private static final Comparator<UInt256> stakeOrdering = Comparator.reverseOrder();
private static final Comparator<Map.Entry<ECPublicKey, UInt256>> validatorOrdering =
Map.Entry.<ECPublicKey, UInt256>comparingByValue(stakeOrdering).thenComparing(Map.Entry.comparingByKey(keyOrdering));
Map.Entry.<ECPublicKey, UInt256>comparingByValue(stakeOrdering)
.thenComparing(Map.Entry.comparingByKey(keyOrdering));

private final int minValidators;
private final int maxValidators;
Expand All @@ -60,20 +65,22 @@ private StakedValidators(
int maxValidators,
Set<ValidatorParticle> validatorParticles,
Map<ECPublicKey, UInt256> stake,
Map<ECPublicKey, REAddr> owners
Map<ECPublicKey, REAddr> owners,
Map<ECPublicKey, Boolean> delegationFlags
) {
this.minValidators = minValidators;
this.maxValidators = maxValidators;
this.validatorParticles = validatorParticles;
this.stake = stake;
this.owners = owners;
this.delegationFlags = delegationFlags;
}

public static StakedValidators create(
int minValidators,
int maxValidators
) {
return new StakedValidators(minValidators, maxValidators, Set.of(), Map.of(), Map.of());
return new StakedValidators(minValidators, maxValidators, Set.of(), Map.of(), Map.of(), Map.of());
}

public StakedValidators add(ValidatorParticle particle) {
Expand All @@ -82,7 +89,7 @@ public StakedValidators add(ValidatorParticle particle) {
.add(particle)
.build();

return new StakedValidators(minValidators, maxValidators, set, stake, owners);
return new StakedValidators(minValidators, maxValidators, set, stake, owners, delegationFlags);
}

public StakedValidators remove(ValidatorParticle particle) {
Expand All @@ -93,35 +100,46 @@ public StakedValidators remove(ValidatorParticle particle) {
.filter(e -> !e.equals(particle))
.collect(Collectors.toSet()),
stake,
owners
owners,
delegationFlags
);
}

public REAddr getOwner(ECPublicKey validatorKey) {
var s = owners.get(validatorKey);
return (s == null) ? REAddr.ofPubKeyAccount(validatorKey) : s;
return ofNullable(owners.get(validatorKey))
.orElse(REAddr.ofPubKeyAccount(validatorKey));
}

public UInt256 getStake(ECPublicKey validatorKey) {
var s = stake.get(validatorKey);
return (s == null) ? UInt256.ZERO : s;
return ofNullable(stake.get(validatorKey))
.orElse(UInt256.ZERO);
}

public Boolean allowsDelegation(ECPublicKey validatorKey) {
return ofNullable(delegationFlags.get(validatorKey))
.orElse(Boolean.FALSE);
}

public UInt256 getOwnerStake(ECPublicKey key) {
return getOwner(key)
.publicKey()
.map(this::getStake)
.orElse(UInt256.ZERO);
}

public StakedValidators setAllowDelegationFlag(ECPublicKey validatorKey, boolean allowDelegation) {
var nextFlags = replaceEntry(Maps.immutableEntry(validatorKey, allowDelegation), delegationFlags);
return new StakedValidators(minValidators, maxValidators, validatorParticles, stake, owners, nextFlags);
}

public StakedValidators setOwner(ECPublicKey validatorKey, REAddr owner) {
final var nextOwners = Stream.concat(
Stream.of(Maps.immutableEntry(validatorKey, owner)),
this.owners.entrySet().stream().filter(e -> !validatorKey.equals(e.getKey()))
).collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
return new StakedValidators(minValidators, maxValidators, validatorParticles, stake, nextOwners);
var nextOwners = replaceEntry(Maps.immutableEntry(validatorKey, owner), owners);
return new StakedValidators(minValidators, maxValidators, validatorParticles, stake, nextOwners, delegationFlags);
}

public StakedValidators setStake(ECPublicKey delegatedKey, UInt256 amount) {
final var nextStake = Stream.concat(
Stream.of(Maps.immutableEntry(delegatedKey, amount)),
this.stake.entrySet().stream().filter(e -> !delegatedKey.equals(e.getKey()))
).collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));

return new StakedValidators(minValidators, maxValidators, validatorParticles, nextStake, owners);
var nextStake = replaceEntry(Maps.immutableEntry(delegatedKey, amount), stake);
return new StakedValidators(minValidators, maxValidators, validatorParticles, nextStake, owners, delegationFlags);
}

// TODO: Remove add/remove from mainnet
Expand All @@ -130,13 +148,10 @@ public StakedValidators add(ECPublicKey delegatedKey, UInt256 amount) {
return this;
}

final var nextAmount = this.stake.getOrDefault(delegatedKey, UInt256.ZERO).add(amount);
final var nextStakedAmounts = Stream.concat(
Stream.of(Maps.immutableEntry(delegatedKey, nextAmount)),
this.stake.entrySet().stream().filter(e -> !delegatedKey.equals(e.getKey()))
).collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
var nextAmount = stake.getOrDefault(delegatedKey, UInt256.ZERO).add(amount);
var nextStakedAmounts = replaceEntry(Maps.immutableEntry(delegatedKey, nextAmount), stake);

return new StakedValidators(minValidators, maxValidators, validatorParticles, nextStakedAmounts, owners);
return new StakedValidators(minValidators, maxValidators, validatorParticles, nextStakedAmounts, owners, delegationFlags);
}

public StakedValidators remove(ECPublicKey delegatedKey, UInt256 amount) {
Expand All @@ -153,18 +168,15 @@ public StakedValidators remove(ECPublicKey delegatedKey, UInt256 amount) {

if (comparison == 0) {
// remove stake
final var nextStakedAmounts = this.stake.entrySet().stream()
.filter(e -> !delegatedKey.equals(e.getKey()))
.collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
return new StakedValidators(minValidators, maxValidators, validatorParticles, nextStakedAmounts, owners);
var nextStakedAmounts = removeKey(delegatedKey, stake);

return new StakedValidators(minValidators, maxValidators, validatorParticles, nextStakedAmounts, owners, delegationFlags);
} else if (comparison < 0) {
// reduce stake
final var nextAmount = oldAmount.subtract(amount);
final var nextStakedAmounts = Stream.concat(
Stream.of(Maps.immutableEntry(delegatedKey, nextAmount)),
this.stake.entrySet().stream().filter(e -> !delegatedKey.equals(e.getKey()))
).collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
return new StakedValidators(minValidators, maxValidators, validatorParticles, nextStakedAmounts, owners);
var nextAmount = oldAmount.subtract(amount);
var nextStakedAmounts = replaceEntry(Maps.immutableEntry(delegatedKey, nextAmount), stake);

return new StakedValidators(minValidators, maxValidators, validatorParticles, nextStakedAmounts, owners, delegationFlags);
} else {
throw new IllegalStateException("Removing stake which doesn't exist.");
}
Expand All @@ -191,10 +203,11 @@ public BFTValidatorSet toValidatorSet() {
);
}

public <T> List<T> map(BiFunction<ECPublicKey, ValidatorDetails, T> mapper) {
public <T> List<T> map(Function<ValidatorDetails, T> mapper) {
return validatorParticles
.stream()
.map(p -> mapper.apply(p.getKey(), ValidatorDetails.fromParticle(p, getOwner(p.getKey()), getStake(p.getKey()))))
.map(this::fillDetails)
.map(mapper::apply)
.collect(Collectors.toList());
}

Expand All @@ -204,15 +217,15 @@ public long count() {

public <T> Optional<T> mapSingle(ECPublicKey validatorKey, Function<ValidatorDetails, T> mapper) {
return validatorParticles.stream()
.filter(p -> p.getKey().equals(validatorKey))
.filter(particle -> particle.getKey().equals(validatorKey))
.findFirst()
.map(p -> ValidatorDetails.fromParticle(p, getOwner(p.getKey()), getStake(p.getKey())))
.map(this::fillDetails)
.map(mapper);
}

@Override
public int hashCode() {
return Objects.hash(minValidators, maxValidators, validatorParticles, stake, owners);
return Objects.hash(minValidators, maxValidators, validatorParticles, stake, owners, delegationFlags);
}

@Override
Expand All @@ -222,10 +235,21 @@ public boolean equals(Object o) {
}

var other = (StakedValidators) o;
return this.minValidators == other.minValidators
&& this.maxValidators == other.maxValidators
&& Objects.equals(this.validatorParticles, other.validatorParticles)
&& Objects.equals(this.stake, other.stake)
&& Objects.equals(this.owners, other.owners);
return minValidators == other.minValidators
&& maxValidators == other.maxValidators
&& Objects.equals(validatorParticles, other.validatorParticles)
&& Objects.equals(stake, other.stake)
&& Objects.equals(owners, other.owners)
&& Objects.equals(delegationFlags, other.delegationFlags);
}

private ValidatorDetails fillDetails(ValidatorParticle particle) {
return ValidatorDetails.fromParticle(
particle,
getOwner(particle.getKey()),
getStake(particle.getKey()),
getOwnerStake(particle.getKey()),
allowsDelegation(particle.getKey())
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.google.inject.Inject;
import com.radixdlt.atommodel.system.state.ValidatorStakeData;
import com.radixdlt.atommodel.tokens.state.PreparedStake;
import com.radixdlt.atommodel.validators.state.AllowDelegationFlag;
import com.radixdlt.atommodel.validators.state.PreparedValidatorUpdate;
import com.radixdlt.atommodel.validators.state.ValidatorParticle;
import com.radixdlt.constraintmachine.Particle;
Expand Down Expand Up @@ -61,7 +62,8 @@ public Set<Class<? extends Particle>> particleClasses() {
ValidatorParticle.class,
ValidatorStakeData.class,
PreparedStake.class,
PreparedValidatorUpdate.class
PreparedValidatorUpdate.class,
AllowDelegationFlag.class
);
}

Expand All @@ -85,6 +87,9 @@ public BiFunction<StakedValidators, Particle, StakedValidators> outputReducer()
} else if (p instanceof PreparedValidatorUpdate) {
var s = (PreparedValidatorUpdate) p;
return prev.setOwner(s.getValidatorKey(), s.getOwnerAddress());
} else if (p instanceof AllowDelegationFlag) {
var s = (AllowDelegationFlag) p;
return prev.setAllowDelegationFlag(s.getValidatorKey(), s.allowsDelegation());
} else {
var s = (ValidatorStakeData) p;
if (s.getOwnerAddr().isPresent()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,27 @@ public final class ValidatorDetails {
private final String name;
private final String url;
private final UInt256 stake;
private final UInt256 ownerStake;
private final boolean allowDelegation;

private ValidatorDetails(ECPublicKey key, REAddr owner, String name, String url, UInt256 stake) {
private ValidatorDetails(
ECPublicKey key, REAddr owner, String name, String url, UInt256 stake, UInt256 ownerStake, boolean allowDelegation
) {
this.key = key;
this.name = name;
this.owner = owner;
this.url = url;
this.stake = stake;
this.ownerStake = ownerStake;
this.allowDelegation = allowDelegation;
}

public static ValidatorDetails fromParticle(ValidatorParticle particle, REAddr owner, UInt256 stake) {
return new ValidatorDetails(particle.getKey(), owner, particle.getName(), particle.getUrl(), stake);
public static ValidatorDetails fromParticle(
ValidatorParticle particle, REAddr owner, UInt256 stake, UInt256 ownerStake, boolean allowDelegation
) {
return new ValidatorDetails(
particle.getKey(), owner, particle.getName(), particle.getUrl(), stake, ownerStake, allowDelegation
);
}

public REAddr getOwner() {
Expand All @@ -60,4 +70,12 @@ public String getUrl() {
public UInt256 getStake() {
return stake;
}

public UInt256 getOwnerStake() {
return ownerStake;
}

public boolean allowsDelegation() {
return allowDelegation;
}
}
Loading

0 comments on commit a43fe68

Please sign in to comment.