protected async Task ValidateOrigination(RawOriginationContent origination, RawBlock rawBlock) { if (!await Cache.Accounts.ExistsAsync(origination.Source)) { throw new ValidationException("unknown source account"); } if (origination.Metadata.Result.Status == "applied" && origination.Delegate != null) { if (!Cache.Accounts.DelegateExists(origination.Delegate)) { throw new ValidationException("unknown delegate"); } } ValidateFeeBalanceUpdates( origination.Metadata.BalanceUpdates, rawBlock.Metadata.Baker, origination.Source, origination.Fee, rawBlock.Metadata.LevelInfo.Cycle); if (origination.Metadata.Result.BalanceUpdates != null) { ValidateTransferBalanceUpdates( origination.Metadata.Result.BalanceUpdates, origination.Source, origination.Metadata.Result.OriginatedContracts[0], origination.Balance, origination.Metadata.Result.PaidStorageSizeDiff * Protocol.ByteCost, Protocol.OriginationSize * Protocol.ByteCost); } }
protected Task ValidateNonceRevelation(RawNonceRevelationContent revelation, RawBlock rawBlock) { if (revelation.Level % Protocol.BlocksPerCommitment != 0) { throw new ValidationException("invalid seed nonce revelation level"); } if (revelation.Metadata.BalanceUpdates.Count != 1) { throw new ValidationException("invalid seed nonce revelation balance updates count"); } if (!(revelation.Metadata.BalanceUpdates[0] is RewardsUpdate)) { throw new ValidationException("invalid seed nonce revelation balance update type"); } if (revelation.Metadata.BalanceUpdates[0].Change != Protocol.RevelationReward) { throw new ValidationException("invalid seed nonce revelation balance update amount"); } if (!Cache.Accounts.DelegateExists(revelation.Metadata.BalanceUpdates[0].Target) || revelation.Metadata.BalanceUpdates[0].Target != rawBlock.Metadata.Baker) { throw new ValidationException("invalid seed nonce revelation baker"); } return(Task.CompletedTask); }
public async Task Init(RawBlock rawBlock) { var protocol = await Cache.Protocols.GetAsync(rawBlock.Protocol); var votingPeriod = await Cache.Periods.CurrentAsync(); var events = BlockEvents.None; if (rawBlock.Level % protocol.BlocksPerCycle == 1) { events |= BlockEvents.CycleBegin; } else if (rawBlock.Level % protocol.BlocksPerCycle == 0) { events |= BlockEvents.CycleEnd; } if (protocol.FirstLevel == rawBlock.Level) { events |= BlockEvents.ProtocolBegin; } else if (rawBlock.Metadata.Protocol != rawBlock.Metadata.NextProtocol) { events |= BlockEvents.ProtocolEnd; } if (rawBlock.Level == votingPeriod.EndLevel) { events |= BlockEvents.VotingPeriodEnd; } else if (rawBlock.Level > votingPeriod.EndLevel) { events |= BlockEvents.VotingPeriodBegin; } if (rawBlock.Metadata.Deactivated.Count > 0) { events |= BlockEvents.Deactivations; } if (rawBlock.Level % protocol.BlocksPerSnapshot == 0) { events |= BlockEvents.Snapshot; } Block = new Block { Id = Cache.AppState.NextOperationId(), Hash = rawBlock.Hash, Level = rawBlock.Level, Protocol = protocol, Timestamp = rawBlock.Header.Timestamp, Priority = rawBlock.Header.Priority, Baker = Cache.Accounts.GetDelegate(rawBlock.Metadata.Baker), Events = events, Reward = protocol.BlockReward0 }; }
public static async Task <BlockCommit> Apply(ProtocolHandler proto, RawBlock rawBlock) { var commit = new BlockCommit(proto); await commit.Init(rawBlock); await commit.Apply(); return(commit); }
public async Task Init(Block block, RawBlock rawBlock) { if (block.Events.HasFlag(BlockEvents.CycleEnd)) { Protocol = await Cache.Protocols.GetAsync(rawBlock.Protocol); var cycle = (rawBlock.Level - 1) / Protocol.BlocksPerCycle; FreezerUpdates = rawBlock.Metadata.BalanceUpdates.Skip(Protocol.BlockReward0 > 0 ? 3 : 2) .Where(x => x is FreezerUpdate fu && fu.Level == cycle - Protocol.PreservedCycles); } }
protected async Task ValidateEndorsement(RawEndorsementContent endorsement, RawBlock rawBlock) { var lastBlock = await Cache.Blocks.CurrentAsync(); if (endorsement.Level != lastBlock.Level) { throw new ValidationException("invalid endorsed block level"); } if (!Cache.Accounts.DelegateExists(endorsement.Metadata.Delegate)) { throw new ValidationException("invalid endorsement delegate"); } if (endorsement.Metadata.BalanceUpdates.Count != 0 && endorsement.Metadata.BalanceUpdates.Count != (Protocol.BlockReward0 > 0 ? 3 : 2)) { throw new ValidationException("invalid endorsement balance updates count"); } if (endorsement.Metadata.BalanceUpdates.Count > 0) { var contractUpdate = endorsement.Metadata.BalanceUpdates.FirstOrDefault(x => x is ContractUpdate) as ContractUpdate ?? throw new ValidationException("invalid endorsement contract balance updates"); var depostisUpdate = endorsement.Metadata.BalanceUpdates.FirstOrDefault(x => x is DepositsUpdate) as DepositsUpdate ?? throw new ValidationException("invalid endorsement depostis balance updates"); if (contractUpdate.Contract != endorsement.Metadata.Delegate || contractUpdate.Change != -endorsement.Metadata.Slots.Count * Protocol.EndorsementDeposit) { throw new ValidationException("invalid endorsement contract update"); } if (depostisUpdate.Delegate != endorsement.Metadata.Delegate || depostisUpdate.Change != endorsement.Metadata.Slots.Count * Protocol.EndorsementDeposit) { throw new ValidationException("invalid endorsement depostis update"); } if (Cycle >= (Protocol.PreservedCycles + 2)) { var rewardsUpdate = endorsement.Metadata.BalanceUpdates.FirstOrDefault(x => x is RewardsUpdate) as RewardsUpdate ?? throw new ValidationException("invalidendorsement rewards updates"); if (rewardsUpdate.Delegate != endorsement.Metadata.Delegate || rewardsUpdate.Change != GetEndorsementReward(endorsement.Metadata.Slots.Count, lastBlock.Priority)) { throw new ValidationException("invalid endorsement rewards update"); } } } }
protected async Task ValidateTransaction(RawTransactionContent transaction, RawBlock rawBlock) { if (!await Cache.Accounts.ExistsAsync(transaction.Source)) { throw new ValidationException("unknown source account"); } ValidateFeeBalanceUpdates( transaction.Metadata.BalanceUpdates, rawBlock.Metadata.Baker, transaction.Source, transaction.Fee, rawBlock.Metadata.LevelInfo.Cycle); if (transaction.Metadata.Result.BalanceUpdates != null) { ValidateTransferBalanceUpdates( transaction.Metadata.Result.BalanceUpdates, transaction.Source, transaction.Destination, transaction.Amount, transaction.Metadata.Result.PaidStorageSizeDiff * Protocol.ByteCost, transaction.Metadata.Result.AllocatedDestinationContract ? Protocol.OriginationSize * Protocol.ByteCost : 0); } if (transaction.Metadata.InternalResults?.Count > 0) { foreach (var internalContent in transaction.Metadata.InternalResults.Where(x => x is RawInternalTransactionResult)) { var internalTransaction = internalContent as RawInternalTransactionResult; if (!await Cache.Accounts.ExistsAsync(internalTransaction.Source, AccountType.Contract)) { throw new ValidationException("unknown source contract"); } if (internalTransaction.Result.BalanceUpdates != null) { ValidateTransferBalanceUpdates( internalTransaction.Result.BalanceUpdates, internalTransaction.Source, internalTransaction.Destination, internalTransaction.Amount, internalTransaction.Result.PaidStorageSizeDiff * Protocol.ByteCost, internalTransaction.Result.AllocatedDestinationContract ? Protocol.OriginationSize * Protocol.ByteCost : 0, transaction.Source); } } } }
protected Task ValidateProposal(RawProposalContent proposal, RawBlock rawBlock) { if (!Cache.Accounts.DelegateExists(proposal.Source)) { throw new ValidationException("invalid proposal sender"); } if (proposal.Period != rawBlock.Metadata.LevelInfo.VotingPeriod) { throw new ValidationException("invalid proposal voting period"); } return(Task.CompletedTask); }
protected async Task ValidateReveal(RawRevealContent reveal, RawBlock rawBlock) { if (!await Cache.Accounts.ExistsAsync(reveal.Source)) { throw new ValidationException("unknown source account"); } ValidateFeeBalanceUpdates( reveal.Metadata.BalanceUpdates, rawBlock.Metadata.Baker, reveal.Source, reveal.Fee, rawBlock.Metadata.LevelInfo.Cycle); }
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?.Level ?? accusedCycle) != accusedCycle || (lostRewardsUpdate?.Level ?? accusedCycle) != accusedCycle || (lostFeesUpdate?.Level ?? accusedCycle) != accusedCycle) { throw new ValidationException("invalid double baking freezer level"); } return(Task.CompletedTask); }
public async Task Init(Block block, RawBlock rawBlock) { if (block.Events.HasFlag(BlockEvents.Deactivations)) { DeactivationLevel = rawBlock.Level; Delegates = await Db.Delegates .Include(x => x.DelegatedAccounts) .Where(x => x.Staked && rawBlock.Metadata.Deactivated.Contains(x.Address)) .ToListAsync(); } else if (block.Events.HasFlag(BlockEvents.CycleBegin)) { DeactivationLevel = rawBlock.Level; Delegates = await Db.Delegates .Include(x => x.DelegatedAccounts) .Where(x => x.Staked && x.DeactivationLevel == rawBlock.Level) .ToListAsync(); } }
protected async Task ValidateBallot(RawBallotContent ballot, RawBlock rawBlock) { var period = await Cache.Periods.CurrentAsync(); var proposal = await Cache.Proposals.GetAsync((period as ExplorationPeriod)?.ProposalId ?? (period as PromotionPeriod).ProposalId); if (proposal.Hash != ballot.Proposal) { throw new ValidationException("invalid ballot proposal"); } if (!Cache.Accounts.DelegateExists(ballot.Source)) { throw new ValidationException("invalid proposal sender"); } if (ballot.Period != rawBlock.Metadata.LevelInfo.VotingPeriod) { throw new ValidationException("invalid proposal voting period"); } }
protected async Task ValidateDelegation(RawDelegationContent delegation, RawBlock rawBlock) { if (!await Cache.Accounts.ExistsAsync(delegation.Source)) { throw new ValidationException("unknown source account"); } ValidateFeeBalanceUpdates( delegation.Metadata.BalanceUpdates, rawBlock.Metadata.Baker, delegation.Source, delegation.Fee, rawBlock.Metadata.LevelInfo.Cycle); if (delegation.Metadata.Result.Status == "applied" && delegation.Delegate != null) { if (delegation.Source != delegation.Delegate && !Cache.Accounts.DelegateExists(delegation.Delegate)) { throw new ValidationException("unknown delegate account"); } } }
public async Task Init(Block block, RawBlock rawBlock) { if (block.Events.HasFlag(BlockEvents.CycleEnd)) { var protocol = await Cache.Protocols.GetAsync(rawBlock.Protocol); var cycle = (rawBlock.Level - 1) / protocol.BlocksPerCycle; if (rawBlock.Metadata.BalanceUpdates.Skip(protocol.BlockReward0 > 0 ? 3 : 2) .Any(x => x is FreezerUpdate fu && fu.Level != cycle - protocol.PreservedCycles)) { RevelationPanlties = new List <RevelationPenaltyOperation>(); var missedBlocks = await Db.Blocks .Include(x => x.Baker) .Where(x => x.Level % protocol.BlocksPerCommitment == 0 && (x.Level - 1) / protocol.BlocksPerCycle == cycle - 1 && x.RevelationId == null) .ToListAsync(); foreach (var missedBlock in missedBlocks) { Cache.Accounts.Add(missedBlock.Baker); RevelationPanlties.Add(new RevelationPenaltyOperation { Id = Cache.AppState.NextOperationId(), Baker = missedBlock.Baker, Block = block, Level = block.Level, Timestamp = block.Timestamp, MissedLevel = missedBlock.Level, LostReward = missedBlock.Reward, LostFees = missedBlock.Fees }); } } } }
public static async Task <RevelationPenaltyCommit> Apply(ProtocolHandler proto, Block block, RawBlock rawBlock) { var commit = new RevelationPenaltyCommit(proto); await commit.Init(block, rawBlock); await commit.Apply(); return(commit); }
public async Task Init(Block block, RawBlock rawBlock) { if (block.Events.HasFlag(BlockEvents.VotingPeriodEnd)) { Event = BlockEvents.VotingPeriodEnd; Period = await Cache.Periods.CurrentAsync(); Period.Epoch ??= await Db.VotingEpoches.FirstOrDefaultAsync(x => x.Id == Period.EpochId); } else if (block.Events.HasFlag(BlockEvents.VotingPeriodBegin)) { Event = BlockEvents.VotingPeriodBegin; var protocol = await Cache.Protocols.GetAsync(rawBlock.Protocol); var currentPeriod = await Cache.Periods.CurrentAsync(); var currentEpoch = await Db.VotingEpoches.FirstOrDefaultAsync(x => x.Id == currentPeriod.EpochId); if (rawBlock.Metadata.VotingPeriod == "proposal") { #region start proposal period Period = new ProposalPeriod { Code = currentPeriod.Code + 1, Epoch = new VotingEpoch { Level = rawBlock.Level }, Kind = VotingPeriods.Proposal, StartLevel = rawBlock.Level, EndLevel = rawBlock.Level + protocol.BlocksPerVoting - 1 }; #endregion } else if (rawBlock.Metadata.VotingPeriod == "testing_vote") { #region start exploration period var proposal = await Db.Proposals .Where(x => x.ProposalPeriodId == currentPeriod.Id) .OrderByDescending(x => x.Upvotes) .FirstAsync(); Cache.Proposals.Add(proposal); Period = new ExplorationPeriod { Code = currentPeriod.Code + 1, Epoch = currentEpoch, Kind = VotingPeriods.Exploration, StartLevel = rawBlock.Level, EndLevel = rawBlock.Level + protocol.BlocksPerVoting - 1, Proposal = proposal, ProposalId = proposal.Id }; #endregion } else if (rawBlock.Metadata.VotingPeriod == "testing") { #region start testing period Period = new TestingPeriod { Code = currentPeriod.Code + 1, Epoch = currentEpoch, Kind = VotingPeriods.Testing, StartLevel = rawBlock.Level, EndLevel = rawBlock.Level + protocol.BlocksPerVoting - 1, Proposal = await Cache.Proposals.GetAsync((currentPeriod as ExplorationPeriod).ProposalId), ProposalId = (currentPeriod as ExplorationPeriod).ProposalId }; #endregion } else if (rawBlock.Metadata.VotingPeriod == "promotion_vote") { #region start promotion period Period = new PromotionPeriod { Code = currentPeriod.Code + 1, Epoch = currentEpoch, Kind = VotingPeriods.Promotion, StartLevel = rawBlock.Level, EndLevel = rawBlock.Level + protocol.BlocksPerVoting - 1, Proposal = await Cache.Proposals.GetAsync((currentPeriod as TestingPeriod).ProposalId), ProposalId = (currentPeriod as TestingPeriod).ProposalId }; #endregion } else { throw new Exception("invalid voting period"); } if (!(Period is TestingPeriod)) { var gracePeriod = GracePeriod.Init(block); // TODO: fix crutch var delegates = await Db.Delegates .AsNoTracking() .Where(x => x.Staked && x.DeactivationLevel < gracePeriod && x.StakingBalance >= protocol.TokensPerRoll) .ToListAsync(); var lastBlock = await Cache.Blocks.CurrentAsync(); lastBlock.Protocol ??= await Cache.Protocols.GetAsync(lastBlock.ProtoCode); Rolls = new List <VotingSnapshot>(delegates.Count); foreach (var delegat in delegates) { Rolls.Add(new VotingSnapshot { Level = lastBlock.Level, Period = Period, DelegateId = delegat.Id, Rolls = (int)(delegat.StakingBalance / lastBlock.Protocol.TokensPerRoll) }); } if (Period is ExplorationPeriod exploration) { exploration.TotalStake = Rolls.Sum(x => x.Rolls); } else if (Period is PromotionPeriod promotion) { promotion.TotalStake = Rolls.Sum(x => x.Rolls); } } } }
public static async Task <VotingCommit> Apply(ProtocolHandler proto, Block block, RawBlock rawBlock) { var commit = new VotingCommit(proto); await commit.Init(block, rawBlock); await commit.Apply(); return(commit); }