示例#1
0
 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)));
        }