public async Task Init(Block block, RawOperation op, RawTransactionContent content) { var sender = await Cache.Accounts.GetAsync(content.Source); sender.Delegate ??= Cache.Accounts.GetDelegate(sender.DelegateId); var target = await Cache.Accounts.GetAsync(content.Destination) ?? block.Originations?.FirstOrDefault(x => x.Contract.Address == content.Destination)?.Contract; if (target != null) { target.Delegate ??= Cache.Accounts.GetDelegate(target.DelegateId); } Transaction = new TransactionOperation { Id = Cache.AppState.NextOperationId(), Block = block, Level = block.Level, Timestamp = block.Timestamp, OpHash = op.Hash, Amount = content.Amount, BakerFee = content.Fee, Counter = content.Counter, GasLimit = content.GasLimit, StorageLimit = content.StorageLimit, Sender = sender, Target = target, Parameters = OperationParameters.Parse(content.Parameters), Status = content.Metadata.Result.Status switch { "applied" => OperationStatus.Applied, "backtracked" => OperationStatus.Backtracked, "failed" => OperationStatus.Failed, "skipped" => OperationStatus.Skipped, _ => throw new Exception($"Invalid status '{content.Metadata.Result.Status}'") },
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); } } foreach (var internalContent in transaction.Metadata.InternalResults.Where(x => x is RawInternalDelegationResult)) { var internalDelegation = internalContent as RawInternalDelegationResult; if (!await Cache.Accounts.ExistsAsync(internalDelegation.Source, AccountType.Contract)) { throw new ValidationException("unknown source contract"); } if (internalDelegation.Result.Status == "applied" && internalDelegation.Delegate != null) { if (!Cache.Accounts.DelegateExists(internalDelegation.Delegate)) { throw new ValidationException("unknown delegate account"); } } } foreach (var internalContent in transaction.Metadata.InternalResults.Where(x => x is RawInternalOriginationResult)) { var internalOrigination = internalContent as RawInternalOriginationResult; if (!await Cache.Accounts.ExistsAsync(internalOrigination.Source, AccountType.Contract)) { throw new ValidationException("unknown source contract"); } if (internalOrigination.Result.Status == "applied" && internalOrigination.Delegate != null) { if (!Cache.Accounts.DelegateExists(internalOrigination.Delegate)) { throw new ValidationException("unknown delegate account"); } } if (internalOrigination.Result.BalanceUpdates != null) { ValidateTransferBalanceUpdates( internalOrigination.Result.BalanceUpdates, internalOrigination.Source, internalOrigination.Result.OriginatedContracts[0], internalOrigination.Balance, internalOrigination.Result.PaidStorageSizeDiff * Protocol.ByteCost, Protocol.OriginationSize * Protocol.ByteCost, transaction.Source); } } } }