public Task Validate(ParsedMutation mutation, IReadOnlyList <SignatureEvidence> authentication, IReadOnlyDictionary <AccountKey, AccountStatus> accounts) { if (this.alwaysValid) { return(Task.FromResult(0)); } else { throw new TransactionInvalidException("Disabled"); } }
public async Task Validate(ParsedMutation mutation, IReadOnlyList <SignatureEvidence> authentication, IReadOnlyDictionary <AccountKey, AccountStatus> accounts) { await ValidateAccountMutations(mutation.AccountMutations, accounts, authentication); await ValidateDataMutations(mutation.DataRecords, authentication); }
public async Task <ByteString> PostTransaction(ByteString rawMutation, IReadOnlyList <SignatureEvidence> authentication) { Mutation mutation; try { // Verify that the mutation can be deserialized mutation = MessageSerializer.DeserializeMutation(rawMutation); } catch (InvalidProtocolBufferException) { throw new TransactionInvalidException("InvalidMutation"); } if (!mutation.Namespace.Equals(this.ledgerId)) { throw new TransactionInvalidException("InvalidNamespace"); } if (mutation.Records.Any(record => record.Key.Value.Count > MaxKeySize)) { throw new TransactionInvalidException("InvalidMutation"); } ValidateAuthentication(authentication, MessageSerializer.ComputeHash(rawMutation.ToByteArray())); ParsedMutation parsedMutation = ParsedMutation.Parse(mutation); // All assets must have an overall zero balance IReadOnlyDictionary <AccountKey, AccountStatus> accounts = await this.store.GetAccounts(parsedMutation.AccountMutations.Select(entry => entry.AccountKey)); var groups = parsedMutation.AccountMutations .GroupBy(account => account.AccountKey.Asset.FullPath) .Select(group => group.Sum(entry => entry.Balance - accounts[entry.AccountKey].Balance)); if (groups.Any(group => group != 0)) { throw new TransactionInvalidException("UnbalancedTransaction"); } DateTime date = DateTime.UtcNow; await this.validator.Validate(parsedMutation, authentication, accounts); TransactionMetadata metadata = new TransactionMetadata(authentication); byte[] rawMetadata = SerializeMetadata(metadata); Transaction transaction = new Transaction(rawMutation, date, new ByteString(rawMetadata)); byte[] serializedTransaction = MessageSerializer.SerializeTransaction(transaction); try { await this.store.AddTransactions(new[] { new ByteString(serializedTransaction) }); } catch (ConcurrentMutationException) { throw new TransactionInvalidException("OptimisticConcurrency"); } return(new ByteString(MessageSerializer.ComputeHash(serializedTransaction))); }