protected Task ValidateDoubleEndorsing(RawDoubleEndorsingEvidenceContent de, RawBlock rawBlock) { if (de.Op1.Operations.Kind != "endorsement" || de.Op2.Operations.Kind != "endorsement") { throw new ValidationException("inconsistent double endorsing operations kind"); } if (de.Op1.Operations.Level != de.Op2.Operations.Level) { throw new ValidationException("inconsistent double endorsing levels"); } var rewardUpdate = de.Metadata.BalanceUpdates.FirstOrDefault(x => x.Change > 0) as RewardsUpdate ?? throw new ValidationException("double endorsing reward is missed"); if (rewardUpdate.Delegate != rawBlock.Metadata.Baker) { throw new ValidationException("invalid double endorsing reward recipient"); } var lostDepositsUpdate = de.Metadata.BalanceUpdates.FirstOrDefault(x => x is DepositsUpdate && x.Change < 0) as DepositsUpdate; var lostRewardsUpdate = de.Metadata.BalanceUpdates.FirstOrDefault(x => x is RewardsUpdate && x.Change < 0) as RewardsUpdate; var lostFeesUpdate = de.Metadata.BalanceUpdates.FirstOrDefault(x => x is FeesUpdate && x.Change < 0) as FeesUpdate; var offender = lostDepositsUpdate?.Delegate ?? lostRewardsUpdate?.Delegate ?? lostFeesUpdate?.Delegate; if (!Cache.Accounts.DelegateExists(offender)) { throw new ValidationException("invalid double endorsing offender"); } if ((lostDepositsUpdate?.Delegate ?? offender) != offender || (lostRewardsUpdate?.Delegate ?? offender) != offender || (lostFeesUpdate?.Delegate ?? offender) != offender) { throw new ValidationException("invalid double endorsing offender updates"); } if (rewardUpdate.Change != -((lostDepositsUpdate?.Change ?? 0) + (lostFeesUpdate?.Change ?? 0)) / 2) { throw new ValidationException("invalid double endorsing reward amount"); } var accusedCycle = (de.Op1.Operations.Level - 1) / Protocol.BlocksPerCycle; if ((lostDepositsUpdate?.Cycle ?? accusedCycle) != accusedCycle || (lostRewardsUpdate?.Cycle ?? accusedCycle) != accusedCycle || (lostFeesUpdate?.Cycle ?? accusedCycle) != accusedCycle) { throw new ValidationException("invalid double endorsing freezer level"); } return(Task.CompletedTask); }
public Task Init(Block block, RawOperation op, RawDoubleEndorsingEvidenceContent content) { DoubleEndorsing = new DoubleEndorsingOperation { Id = Cache.AppState.NextOperationId(), Block = block, Level = block.Level, Timestamp = block.Timestamp, OpHash = op.Hash, AccusedLevel = content.Op1.Operations.Level, Accuser = block.Baker, Offender = Cache.Accounts.GetDelegate(content.Metadata.BalanceUpdates.First(x => x.Change < 0).Target), AccuserReward = content.Metadata.BalanceUpdates.Where(x => x.Change > 0).Sum(x => x.Change), OffenderLostDeposit = content.Metadata.BalanceUpdates.Where(x => x.Change < 0 && x is DepositsUpdate).Sum(x => - x.Change), OffenderLostReward = content.Metadata.BalanceUpdates.Where(x => x.Change < 0 && x is RewardsUpdate).Sum(x => - x.Change), OffenderLostFee = content.Metadata.BalanceUpdates.Where(x => x.Change < 0 && x is FeesUpdate).Sum(x => - x.Change) }; return(Task.CompletedTask); }
public static async Task <DoubleEndorsingCommit> Apply(ProtocolHandler proto, Block block, RawOperation op, RawDoubleEndorsingEvidenceContent content) { var commit = new DoubleEndorsingCommit(proto); await commit.Init(block, op, content); await commit.Apply(); return(commit); }