protected Task ValidateDoubleBaking(RawDoubleBakingEvidenceContent db, RawBlock rawBlock) { if (db.Block1.Level != db.Block2.Level) { throw new ValidationException("inconsistent double baking levels"); } var rewardUpdate = db.Metadata.BalanceUpdates.FirstOrDefault(x => x.Change > 0) as RewardsUpdate ?? throw new ValidationException("double baking reward is missed"); if (rewardUpdate.Delegate != rawBlock.Metadata.Baker) { throw new ValidationException("invalid double baking reward recipient"); } var lostDepositsUpdate = db.Metadata.BalanceUpdates.FirstOrDefault(x => x is DepositsUpdate && x.Change < 0) as DepositsUpdate; var lostRewardsUpdate = db.Metadata.BalanceUpdates.FirstOrDefault(x => x is RewardsUpdate && x.Change < 0) as RewardsUpdate; var lostFeesUpdate = db.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 baking offender"); } if ((lostDepositsUpdate?.Delegate ?? offender) != offender || (lostRewardsUpdate?.Delegate ?? offender) != offender || (lostFeesUpdate?.Delegate ?? offender) != offender) { throw new ValidationException("invalid double baking offender updates"); } if (rewardUpdate.Change != -((lostDepositsUpdate?.Change ?? 0) + (lostFeesUpdate?.Change ?? 0)) / 2) { throw new ValidationException("invalid double baking reward amount"); } var accusedCycle = (db.Block1.Level - 1) / Protocol.BlocksPerCycle; if ((lostDepositsUpdate?.Cycle ?? accusedCycle) != accusedCycle || (lostRewardsUpdate?.Cycle ?? accusedCycle) != accusedCycle || (lostFeesUpdate?.Cycle ?? accusedCycle) != accusedCycle) { throw new ValidationException("invalid double baking freezer level"); } return(Task.CompletedTask); }
public Task Init(Block block, RawOperation op, RawDoubleBakingEvidenceContent content) { DoubleBaking = new DoubleBakingOperation { Id = Cache.AppState.NextOperationId(), Block = block, Level = block.Level, Timestamp = block.Timestamp, OpHash = op.Hash, AccusedLevel = content.Block1.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 <DoubleBakingCommit> Apply(ProtocolHandler proto, Block block, RawOperation op, RawDoubleBakingEvidenceContent content) { var commit = new DoubleBakingCommit(proto); await commit.Init(block, op, content); await commit.Apply(); return(commit); }