private async Task TransfertInternal(string from, string to, long amount, string asset)
        {
            var lAsset   = LedgerPath.Parse(asset);
            var aFrom    = new AccountKey(LedgerPath.Parse(from), lAsset);
            var aTo      = new AccountKey(LedgerPath.Parse(to), lAsset);
            var accounts = await Engine.GetAccounts(new[] { aFrom, aTo });

            var adFrom = accounts[aFrom];
            var adTo   = accounts[aTo];

            var rFrom = new Record(aFrom.Key.ToBinary(), LongToByteString(adFrom.Balance - amount), adFrom.Version);
            var rTo   = new Record(aTo.Key.ToBinary(), LongToByteString(adTo.Balance + amount), adTo.Version);

            Mutation m = new Mutation(ByteString.Empty, new[] { rFrom, rTo }, ByteString.Empty);

            int c = System.Threading.Interlocked.Increment(ref gcounter);

            Transaction t = new Transaction(
                new ByteString(MessageSerializer.SerializeMutation(m)),
                DateTime.UtcNow,
                new ByteString(BitConverter.GetBytes(c))
                );

            await Engine.AddTransactions(new[] { new ByteString(MessageSerializer.SerializeTransaction(t)) });

            //Output.WriteLine($"{prefix} - {from} ==> {to} Success Retry : {tryCount}");
        }
예제 #2
0
        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");
            }

            ParsedMutation parsedMutation = ParsedMutation.Parse(mutation);

            IReadOnlyDictionary <AccountKey, AccountStatus> accounts = await ValidateMutation(mutation, parsedMutation);

            ValidateAuthentication(authentication, MessageSerializer.ComputeHash(rawMutation.ToByteArray()));

            DateTime date = DateTime.UtcNow;

            IList <Mutation> generatedMutations = 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);

            List <ByteString> transactions = new List <ByteString>()
            {
                new ByteString(serializedTransaction)
            };

            transactions.AddRange(await Task.WhenAll(generatedMutations.Select(async generatedMutation =>
            {
                await ValidateMutation(generatedMutation, ParsedMutation.Parse(generatedMutation));
                Transaction generatedTransaction = new Transaction(new ByteString(MessageSerializer.SerializeMutation(generatedMutation)), date, ByteString.Empty);
                return(new ByteString(MessageSerializer.SerializeTransaction(generatedTransaction)));
            })));

            try
            {
                await this.store.AddTransactions(transactions);
            }
            catch (ConcurrentMutationException)
            {
                throw new TransactionInvalidException("OptimisticConcurrency");
            }

            return(new ByteString(MessageSerializer.ComputeHash(serializedTransaction)));
        }
        private async Task <ByteString> AddTransaction(params Record[] records)
        {
            Mutation    mutation           = new Mutation(ByteString.Parse("0123"), records, ByteString.Parse("4567"));
            ByteString  serializedMutation = new ByteString(MessageSerializer.SerializeMutation(mutation));
            Transaction transaction        = new Transaction(
                serializedMutation,
                new DateTime(1, 2, 3, 4, 5, 6),
                ByteString.Parse("abcdef"));

            await this.Store.AddTransactions(new[] { new ByteString(MessageSerializer.SerializeTransaction(transaction)) });

            return(new ByteString(MessageSerializer.ComputeHash(serializedMutation.ToByteArray())));
        }
        public void Transaction_Success()
        {
            Transaction transaction = new Transaction(
                binaryData[0],
                new DateTime(1, 2, 3, 4, 5, 6),
                binaryData[1]);

            byte[] result = MessageSerializer.SerializeTransaction(transaction);

            Transaction finalTransaction = MessageSerializer.DeserializeTransaction(new ByteString(result));

            Assert.Equal(79, result.Length);
            Assert.Equal(transaction.Mutation, finalTransaction.Mutation);
            Assert.Equal(transaction.Timestamp, finalTransaction.Timestamp);
            Assert.Equal(transaction.TransactionMetadata, finalTransaction.TransactionMetadata);
        }
        private ByteString AddRecord(string key)
        {
            Mutation mutation = new Mutation(
                ByteString.Empty,
                new Record[] { new Record(new ByteString(Encoding.UTF8.GetBytes(key)), ByteString.Empty, ByteString.Empty) },
                ByteString.Empty);

            Transaction transaction = new Transaction(
                new ByteString(MessageSerializer.SerializeMutation(mutation)),
                new DateTime(),
                ByteString.Empty);

            this.transactions.Add(new ByteString(MessageSerializer.SerializeTransaction(transaction)));

            return(new ByteString(MessageSerializer.ComputeHash(MessageSerializer.SerializeTransaction(transaction))));
        }
        private async Task AddRecords(params string[] keys)
        {
            Mutation mutation = new Mutation(
                ByteString.Empty,
                keys.Select(key => new Record(
                                new ByteString(Encoding.UTF8.GetBytes(key)),
                                ByteString.Empty,
                                ByteString.Empty)),
                ByteString.Empty);

            Transaction transaction = new Transaction(
                new ByteString(MessageSerializer.SerializeMutation(mutation)),
                new DateTime(),
                ByteString.Empty);

            await store.AddTransactions(new[] { new ByteString(MessageSerializer.SerializeTransaction(transaction)) });
        }
        private ByteString CreateTransaction(params string[] keys)
        {
            Mutation mutation = new Mutation(
                ByteString.Empty,
                keys.Select(key => new Record(
                                new ByteString(Encoding.UTF8.GetBytes(key)),
                                ByteString.Parse("ab"),
                                ByteString.Parse("cd"))),
                ByteString.Empty);

            byte[] serializedMutation = MessageSerializer.SerializeMutation(mutation);

            Transaction transaction = new Transaction(
                new ByteString(MessageSerializer.SerializeMutation(mutation)),
                new DateTime(),
                ByteString.Empty);

            return(new ByteString(MessageSerializer.SerializeTransaction(transaction)));
        }
예제 #8
0
        private async Task <ByteString> AddRecords(ByteString version, ByteString value, params string[] keys)
        {
            Mutation mutation = new Mutation(
                ByteString.Empty,
                keys.Select(key => new Record(
                                new ByteString(Encoding.UTF8.GetBytes(key)),
                                value,
                                version)),
                ByteString.Empty);

            byte[] serializedMutation = MessageSerializer.SerializeMutation(mutation);

            Transaction transaction = new Transaction(
                new ByteString(MessageSerializer.SerializeMutation(mutation)),
                new DateTime(),
                ByteString.Empty);

            await Engine.AddTransactions(new[] { new ByteString(MessageSerializer.SerializeTransaction(transaction)) });

            return(new ByteString(MessageSerializer.ComputeHash(serializedMutation)));
        }
        public async Task AddTransaction_MultipleTransactionsSuccess()
        {
            IList <Record> records1 = new Record[]
            {
                new Record(binaryData[0], binaryData[1], ByteString.Empty),
                new Record(binaryData[2], binaryData[3], ByteString.Empty),
            };

            ByteString mutation1     = new ByteString(MessageSerializer.SerializeMutation(new Mutation(ByteString.Empty, records1, ByteString.Empty)));
            ByteString mutationHash1 = new ByteString(MessageSerializer.ComputeHash(mutation1.ToByteArray()));

            IList <Record> records2 = new Record[]
            {
                new Record(binaryData[2], binaryData[5], mutationHash1),
                new Record(binaryData[6], binaryData[7], ByteString.Empty),
            };

            ByteString mutation2     = new ByteString(MessageSerializer.SerializeMutation(new Mutation(ByteString.Empty, records2, ByteString.Empty)));
            ByteString mutationHash2 = new ByteString(MessageSerializer.ComputeHash(mutation2.ToByteArray()));

            // Submit both transactions at once
            await this.Store.AddTransactions(new[]
            {
                new ByteString(MessageSerializer.SerializeTransaction(new Transaction(mutation1, new DateTime(), ByteString.Empty))),
                new ByteString(MessageSerializer.SerializeTransaction(new Transaction(mutation2, new DateTime(), ByteString.Empty)))
            });

            IReadOnlyList <Record> result1 = await this.Store.GetRecords(new[] { binaryData[0] });

            IReadOnlyList <Record> result2 = await this.Store.GetRecords(new[] { binaryData[2] });

            IReadOnlyList <Record> result3 = await this.Store.GetRecords(new[] { binaryData[6] });

            AssertRecord(result1[0], binaryData[0], binaryData[1], mutationHash1);
            AssertRecord(result2[0], binaryData[2], binaryData[5], mutationHash2);
            AssertRecord(result3[0], binaryData[6], binaryData[7], mutationHash2);
        }
        public async Task AddTransaction_MultipleTransactionsError()
        {
            IList <Record> records1 = new Record[]
            {
                new Record(binaryData[0], binaryData[1], ByteString.Empty),
                new Record(binaryData[2], binaryData[3], ByteString.Empty),
            };

            ByteString mutation1 = new ByteString(MessageSerializer.SerializeMutation(new Mutation(ByteString.Empty, records1, ByteString.Empty)));

            IList <Record> records2 = new Record[]
            {
                new Record(binaryData[2], binaryData[5], ByteString.Empty),
                new Record(binaryData[6], binaryData[7], ByteString.Empty),
            };

            ByteString mutation2 = new ByteString(MessageSerializer.SerializeMutation(new Mutation(ByteString.Empty, records2, ByteString.Empty)));

            // Submit both transactions at once
            ConcurrentMutationException exception = await Assert.ThrowsAsync <ConcurrentMutationException>(() => this.Store.AddTransactions(new[]
            {
                new ByteString(MessageSerializer.SerializeTransaction(new Transaction(mutation1, new DateTime(), ByteString.Empty))),
                new ByteString(MessageSerializer.SerializeTransaction(new Transaction(mutation2, new DateTime(), ByteString.Empty)))
            }));

            IReadOnlyList <Record> result1 = await this.Store.GetRecords(new[] { binaryData[0] });

            IReadOnlyList <Record> result2 = await this.Store.GetRecords(new[] { binaryData[2] });

            IReadOnlyList <Record> result3 = await this.Store.GetRecords(new[] { binaryData[6] });

            AssertRecord(exception.FailedMutation, binaryData[2], binaryData[5], ByteString.Empty);
            AssertRecord(result1[0], binaryData[0], ByteString.Empty, ByteString.Empty);
            AssertRecord(result2[0], binaryData[2], ByteString.Empty, ByteString.Empty);
            AssertRecord(result3[0], binaryData[6], ByteString.Empty, ByteString.Empty);
        }
예제 #11
0
        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.Namespace))
            {
                throw new TransactionInvalidException("InvalidNamespace");
            }

            if (mutation.Records.Count == 0)
            {
                throw new TransactionInvalidException("InvalidMutation");
            }

            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)));
        }