Skip to content

Commit

Permalink
Implement new slashing mechanics
Browse files Browse the repository at this point in the history
  • Loading branch information
Groxan committed Jan 16, 2024
1 parent dbf3de5 commit 82de8c8
Show file tree
Hide file tree
Showing 24 changed files with 583 additions and 425 deletions.
5 changes: 1 addition & 4 deletions Tzkt.Data/Models/Accounts/Delegate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public class Delegate : User
public long IssuedPseudotokens { get; set; }
public int StakersCount { get; set; }

public long? FrozenDepositLimit { get; set; }
public long? LimitOfStakingOverBaking { get; set; }
public long? EdgeOfBakingOverStaking { get; set; }

Expand All @@ -38,10 +39,6 @@ public class Delegate : User

public int? SoftwareId { get; set; }

#region legacy
public long? FrozenDepositLimit { get; set; }
#endregion

#region relations
[ForeignKey(nameof(SoftwareId))]
public Software Software { get; set; }
Expand Down
31 changes: 17 additions & 14 deletions Tzkt.Data/Models/Blocks/BlockEvents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,22 @@ namespace Tzkt.Data.Models
[Flags]
public enum BlockEvents
{
None = 0b_0000_0000_0000_0000,
CycleBegin = 0b_0000_0000_0000_0001,
CycleEnd = 0b_0000_0000_0000_0010,
ProtocolBegin = 0b_0000_0000_0000_0100,
ProtocolEnd = 0b_0000_0000_0000_1000,
Deactivations = 0b_0000_0000_0001_0000,
NewAccounts = 0b_0000_0000_0010_0000,
BalanceSnapshot = 0b_0000_0000_0100_0000,
SmartContracts = 0b_0000_0000_1000_0000,
DelegatorContracts = 0b_0000_0001_0000_0000,
Bigmaps = 0b_0000_0010_0000_0000,
Tokens = 0b_0000_0100_0000_0000,
Events = 0b_0000_1000_0000_0000,
Tickets = 0b_0001_0000_0000_0000
None = 0b_0000_0000_0000_0000,
CycleBegin = 0b_0000_0000_0000_0001,
CycleEnd = 0b_0000_0000_0000_0010,
ProtocolBegin = 0b_0000_0000_0000_0100,
ProtocolEnd = 0b_0000_0000_0000_1000,
Deactivations = 0b_0000_0000_0001_0000,
NewAccounts = 0b_0000_0000_0010_0000,
BalanceSnapshot = 0b_0000_0000_0100_0000,
SmartContracts = 0b_0000_0000_1000_0000,
DelegatorContracts = 0b_0000_0001_0000_0000,
Bigmaps = 0b_0000_0010_0000_0000,
Tokens = 0b_0000_0100_0000_0000,
Events = 0b_0000_1000_0000_0000,
Tickets = 0b_0001_0000_0000_0000,
DoubleBakingSlashing = 0b_0010_0000_0000_0000,
DoubleEndorsingSlashing = 0b_0100_0000_0000_0000,
DoublePreendorsingSlashing = 0b_1000_0000_0000_0000
}
}
13 changes: 2 additions & 11 deletions Tzkt.Data/Models/Blocks/Protocol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,17 +81,8 @@ public class Protocol
public int VdfRevelationRewardWeight { get; set; }
public int LBSubsidyWeight { get; set; }

public int AdaptiveIssuanceLaunchEmaThreshold { get; set; }
public int AdaptiveIssuanceRatioMinNumerator { get; set; }
public int AdaptiveIssuanceRatioMinDenominator { get; set; }
public int AdaptiveIssuanceRatioMaxNumerator { get; set; }
public int AdaptiveIssuanceRatioMaxDenominator { get; set; }
public int AdaptiveIssuanceCenterDzNumerator { get; set; }
public int AdaptiveIssuanceCenterDzDenominator { get; set; }
public int AdaptiveIssuanceRadiusDzNumerator { get; set; }
public int AdaptiveIssuanceRadiusDzDenominator { get; set; }
public long AdaptiveIssuanceMaxBonus { get; set; }
public long AdaptiveIssuanceGrowthRate { get; set; }
public int DoubleBakingSlashedPercentage { get; set; }
public int DoubleEndorsingSlashedPercentage { get; set; }

#region helpers
public int GetCycleStart(int cycle)
Expand Down
1 change: 1 addition & 0 deletions Tzkt.Data/Models/Operations/DoubleBakingOperation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace Tzkt.Data.Models
public class DoubleBakingOperation : BaseOperation
{
public int AccusedLevel { get; set; }
public int SlashedLevel { get; set; }

public int AccuserId { get; set; }
public long AccuserReward { get; set; }
Expand Down
1 change: 1 addition & 0 deletions Tzkt.Data/Models/Operations/DoubleEndorsingOperation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace Tzkt.Data.Models
public class DoubleEndorsingOperation : BaseOperation
{
public int AccusedLevel { get; set; }
public int SlashedLevel { get; set; }

public int AccuserId { get; set; }
public long AccuserReward { get; set; }
Expand Down
1 change: 1 addition & 0 deletions Tzkt.Data/Models/Operations/DoublePreendorsingOperation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace Tzkt.Data.Models
public class DoublePreendorsingOperation : BaseOperation
{
public int AccusedLevel { get; set; }
public int SlashedLevel { get; set; }

public int AccuserId { get; set; }
public long AccuserReward { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public virtual void Apply(Block block, JsonElement op, JsonElement content)
Timestamp = block.Timestamp,
OpHash = op.RequiredString("hash"),

SlashedLevel = block.Level,
AccusedLevel = content.Required("bh1").RequiredInt32("level"),
Accuser = block.Proposer,
Offender = Cache.Accounts.GetDelegate(offenderAddr),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public virtual void Apply(Block block, JsonElement op, JsonElement content)
Timestamp = block.Timestamp,
OpHash = op.RequiredString("hash"),

SlashedLevel = block.Level,
AccusedLevel = content.Required("op1").Required("operations").RequiredInt32("level") + 1,
Accuser = block.Proposer,
Offender = Cache.Accounts.GetDelegate(offenderAddr),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public virtual void Apply(Block block, JsonElement op, JsonElement content)
Timestamp = block.Timestamp,
OpHash = op.RequiredString("hash"),

SlashedLevel = block.Level,
AccusedLevel = content.Required("op1").Required("operations").RequiredInt32("level"),
Accuser = block.Proposer,
Offender = Cache.Accounts.GetDelegate(offenderAddr),
Expand Down
27 changes: 4 additions & 23 deletions Tzkt.Sync/Protocols/Handlers/Proto18/Activation/ProtoActivator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,17 +152,8 @@ protected override void SetParameters(Protocol protocol, JToken parameters)
protocol.VdfRevelationRewardWeight = parameters["issuance_weights"]?["vdf_revelation_tip_weight"]?.Value<int>() ?? 1;
protocol.LBSubsidyWeight = parameters["issuance_weights"]?["liquidity_baking_subsidy_weight"]?.Value<int>() ?? 1280;

protocol.AdaptiveIssuanceLaunchEmaThreshold = parameters["adaptive_issuance_launch_ema_threshold"]?.Value<int>() ?? 100_000_000;
protocol.AdaptiveIssuanceRatioMinNumerator = parameters["adaptive_rewards_params"]?["issuance_ratio_min"]?["numerator"]?.Value<int>() ?? 1;
protocol.AdaptiveIssuanceRatioMinDenominator = parameters["adaptive_rewards_params"]?["issuance_ratio_min"]?["denominator"]?.Value<int>() ?? 2000;
protocol.AdaptiveIssuanceRatioMaxNumerator = parameters["adaptive_rewards_params"]?["issuance_ratio_max"]?["numerator"]?.Value<int>() ?? 1;
protocol.AdaptiveIssuanceRatioMaxDenominator = parameters["adaptive_rewards_params"]?["issuance_ratio_max"]?["denominator"]?.Value<int>() ?? 20;
protocol.AdaptiveIssuanceCenterDzNumerator = parameters["adaptive_rewards_params"]?["center_dz"]?["numerator"]?.Value<int>() ?? 1;
protocol.AdaptiveIssuanceCenterDzDenominator = parameters["adaptive_rewards_params"]?["center_dz"]?["denominator"]?.Value<int>() ?? 2;
protocol.AdaptiveIssuanceRadiusDzNumerator = parameters["adaptive_rewards_params"]?["radius_dz"]?["numerator"]?.Value<int>() ?? 1;
protocol.AdaptiveIssuanceRadiusDzDenominator = parameters["adaptive_rewards_params"]?["radius_dz"]?["denominator"]?.Value<int>() ?? 50;
protocol.AdaptiveIssuanceMaxBonus = parameters["adaptive_rewards_params"]?["max_bonus"]?.Value<long>() ?? 50_000_000_000_000;
protocol.AdaptiveIssuanceGrowthRate = parameters["adaptive_rewards_params"]?["growth_rate"]?.Value<long>() ?? 115_740_740;
protocol.DoubleBakingSlashedPercentage = parameters["percentage_of_frozen_deposits_slashed_per_double_baking"]?.Value<int>() ?? 5;
protocol.DoubleEndorsingSlashedPercentage = parameters["percentage_of_frozen_deposits_slashed_per_double_attestation"]?.Value<int>() ?? 50;

protocol.BlockDeposit = 0;
protocol.BlockReward0 = 0;
Expand All @@ -189,17 +180,8 @@ protected override void UpgradeParameters(Protocol protocol, Protocol prev)
protocol.VdfRevelationRewardWeight = 1;
protocol.LBSubsidyWeight = 1280;

protocol.AdaptiveIssuanceLaunchEmaThreshold = 100_000_000;
protocol.AdaptiveIssuanceRatioMinNumerator = 1;
protocol.AdaptiveIssuanceRatioMinDenominator = 2000;
protocol.AdaptiveIssuanceRatioMaxNumerator = 1;
protocol.AdaptiveIssuanceRatioMaxDenominator = 20;
protocol.AdaptiveIssuanceCenterDzNumerator = 1;
protocol.AdaptiveIssuanceCenterDzDenominator = 2;
protocol.AdaptiveIssuanceRadiusDzNumerator = 1;
protocol.AdaptiveIssuanceRadiusDzDenominator = 50;
protocol.AdaptiveIssuanceMaxBonus = 50_000_000_000_000;
protocol.AdaptiveIssuanceGrowthRate = 115_740_740;
protocol.DoubleBakingSlashedPercentage = 5;
protocol.DoubleEndorsingSlashedPercentage = 50;

protocol.BlockDeposit = 0;
protocol.BlockReward0 = 0;
Expand Down Expand Up @@ -399,7 +381,6 @@ async Task MigrateBakers(AppState state)
foreach (var baker in Cache.Accounts.GetDelegates())
{
Db.TryAttach(baker);
baker.FrozenDepositLimit = null;
baker.StakedBalance = stakes.GetValueOrDefault(baker.Address);
baker.TotalStakedBalance = stakes.GetValueOrDefault(baker.Address);
}
Expand Down
4 changes: 2 additions & 2 deletions Tzkt.Sync/Protocols/Handlers/Proto18/Commits/BlockCommit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public async Task ApplyRewards(JsonElement rawBlock)
nextUpdate.Required("staker").RequiredString("baker") == proposer.Address &&
nextUpdate.RequiredInt64("change") == change)
{
var changeOwn = (long)((BigInteger)change * proposer.StakedBalance / proposer.TotalStakedBalance);
var changeOwn = proposer.TotalStakedBalance == 0 ? change : (long)((BigInteger)change * proposer.StakedBalance / proposer.TotalStakedBalance);
var changeShared = change - changeOwn;
rewardStakedOwn += changeOwn;
rewardStakedShared += changeShared;
Expand Down Expand Up @@ -148,7 +148,7 @@ public async Task ApplyRewards(JsonElement rawBlock)
nextUpdate.Required("staker").RequiredString("baker") == producer.Address &&
nextUpdate.RequiredInt64("change") == change)
{
var changeOwn = (long)((BigInteger)change * producer.StakedBalance / producer.TotalStakedBalance);
var changeOwn = producer.TotalStakedBalance == 0 ? change : (long)((BigInteger)change * producer.StakedBalance / producer.TotalStakedBalance);
var changeShared = change - changeOwn;
bonusStakedOwn += changeOwn;
bonusStakedShared += changeShared;
Expand Down
70 changes: 50 additions & 20 deletions Tzkt.Sync/Protocols/Handlers/Proto18/Commits/CycleCommit.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Numerics;
using Microsoft.EntityFrameworkCore;
using Tzkt.Data.Models;

namespace Tzkt.Sync.Protocols.Proto18
Expand Down Expand Up @@ -26,33 +27,62 @@ public override async Task Apply(Block block)
FutureCycle.LBSubsidy = issuance.RequiredInt64("liquidity_baking_subsidy");
}

protected override Task<Dictionary<int, long>> GetSelectedStakes(Block block)
protected override async Task<Dictionary<int, long>> GetSelectedStakes(Block block)
{
if (block.Cycle == block.Protocol.FirstCycle)
return base.GetSelectedStakes(block);
return await base.GetSelectedStakes(block);

if (block.Cycle <= Cache.AppState.Get().AIActivationCycle)
return Task.FromResult(Snapshots
.Where(x => x.StakingBalance >= block.Protocol.MinimalStake)
.ToDictionary(x => x.AccountId, x => Math.Min(x.StakingBalance, x.TotalStakedBalance * (block.Protocol.MaxDelegatedOverFrozenRatio + 1))));
//if (block.Cycle <= Cache.AppState.Get().AIActivationCycle)
// return Task.FromResult(Snapshots
// .Where(x => x.StakingBalance >= block.Protocol.MinimalStake)
// .ToDictionary(x => x.AccountId, x => Math.Min(x.StakingBalance, x.TotalStakedBalance * (block.Protocol.MaxDelegatedOverFrozenRatio + 1))));

return Task.FromResult(Snapshots
.Select(x =>
var slashings = new Dictionary<int, int>();
var prevBlock = Cache.Blocks.Get(block.Level - 1);
if (prevBlock.Events.HasFlag(BlockEvents.DoubleBakingSlashing))
{
var prevBlockProto = await Cache.Protocols.GetAsync(prevBlock.ProtoCode);
foreach (var op in await Db.DoubleBakingOps.AsNoTracking().Where(x => x.SlashedLevel == block.Level - 1).ToListAsync())
slashings[op.OffenderId] = slashings.GetValueOrDefault(op.OffenderId) + prevBlockProto.DoubleBakingSlashedPercentage;
}
if (prevBlock.Events.HasFlag(BlockEvents.DoubleEndorsingSlashing))
{
var prevBlockProto = await Cache.Protocols.GetAsync(prevBlock.ProtoCode);
foreach (var op in await Db.DoubleEndorsingOps.AsNoTracking().Where(x => x.SlashedLevel == block.Level - 1).ToListAsync())
slashings[op.OffenderId] = slashings.GetValueOrDefault(op.OffenderId) + prevBlockProto.DoubleEndorsingSlashedPercentage;
}
if (prevBlock.Events.HasFlag(BlockEvents.DoublePreendorsingSlashing))
{
var prevBlockProto = await Cache.Protocols.GetAsync(prevBlock.ProtoCode);
foreach (var op in await Db.DoublePreendorsingOps.AsNoTracking().Where(x => x.SlashedLevel == block.Level - 1).ToListAsync())
slashings[op.OffenderId] = slashings.GetValueOrDefault(op.OffenderId) + prevBlockProto.DoubleEndorsingSlashedPercentage;
}

return Snapshots.Select(x =>
{
var ownStaked = x.OwnStakedBalance;
var externalStaked = x.ExternalStakedBalance;
if (slashings.TryGetValue(x.AccountId, out var percentage))
{
var stakingOverBaking = Math.Min(
block.Protocol.MaxExternalOverOwnStakeRatio * 1_000_000,
Cache.Accounts.GetDelegate(x.AccountId).LimitOfStakingOverBaking ?? long.MaxValue);
ownStaked = ownStaked * Math.Max(0, 100 - percentage) / 100;
externalStaked = externalStaked * Math.Max(0, 100 - percentage) / 100;
}
var totalStaked = ownStaked + externalStaked;

var frozen = Math.Min(x.TotalStakedBalance, x.OwnStakedBalance + (long)((BigInteger)x.OwnStakedBalance * stakingOverBaking / 1_000_000));
var delegated = Math.Min(x.StakingBalance - frozen, x.OwnStakedBalance * block.Protocol.MaxDelegatedOverFrozenRatio);
var stakingOverBaking = Math.Min(
block.Protocol.MaxExternalOverOwnStakeRatio * 1_000_000,
Cache.Accounts.GetDelegate(x.AccountId).LimitOfStakingOverBaking ?? long.MaxValue);

return (x.AccountId, frozen, delegated);
})
.Where(x => x.frozen >= block.Protocol.MinimalFrozenStake && x.frozen + x.delegated >= block.Protocol.MinimalStake)
.ToDictionary(x => x.AccountId, x =>
{
return x.frozen + x.delegated;
}));
var frozen = Math.Min(totalStaked, ownStaked + (long)((BigInteger)ownStaked * stakingOverBaking / 1_000_000));
var delegated = Math.Min(x.StakingBalance - frozen, ownStaked * block.Protocol.MaxDelegatedOverFrozenRatio);

return (x.AccountId, frozen, delegated);
})
.Where(x => x.frozen >= block.Protocol.MinimalFrozenStake && x.frozen + x.delegated >= block.Protocol.MinimalStake)
.ToDictionary(x => x.AccountId, x =>
{
return x.frozen + x.delegated;
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public virtual async Task Apply(Block block, JsonElement rawBlock)
if (!ops.TryGetValue(baker.Id, out var op))
throw new Exception("Unexpected endorsing rewards balance update");

var changeOwn = (long)((BigInteger)change * baker.StakedBalance / baker.TotalStakedBalance);
var changeOwn = baker.TotalStakedBalance == 0 ? change : (long)((BigInteger)change * baker.StakedBalance / baker.TotalStakedBalance);
var changeShared = change - changeOwn;
op.RewardStakedOwn = changeOwn;
op.RewardStakedShared = changeShared;
Expand Down
Loading

0 comments on commit 82de8c8

Please sign in to comment.