Esempio n. 1
0
        public void Parse_Error()
        {
            ArgumentNullException exception = Assert.Throws <ArgumentNullException>(() => RecordKey.Parse(null));

            Assert.Equal("keyData", exception.ParamName);

            // Invalid structure
            Assert.Throws <ArgumentOutOfRangeException>(() =>
                                                        RecordKey.Parse(new ByteString(Encoding.UTF8.GetBytes("/account/name/"))));

            // Unknown record type
            Assert.Throws <ArgumentOutOfRangeException>(() =>
                                                        RecordKey.Parse(new ByteString(Encoding.UTF8.GetBytes("/account/name/:DOESNOTEXIST:"))));

            // Incorrect number of additional components
            Assert.Throws <ArgumentOutOfRangeException>(() =>
                                                        RecordKey.Parse(new ByteString(Encoding.UTF8.GetBytes("/asset/name/:ACC:/other/:other"))));

            Assert.Throws <ArgumentOutOfRangeException>(() =>
                                                        RecordKey.Parse(new ByteString(Encoding.UTF8.GetBytes("/asset/name/:ACC"))));

            // Invalid path
            Assert.Throws <ArgumentOutOfRangeException>(() =>
                                                        RecordKey.Parse(new ByteString(Encoding.UTF8.GetBytes("account/name/:ACC:/"))));

            Assert.Throws <ArgumentOutOfRangeException>(() =>
                                                        RecordKey.Parse(new ByteString(Encoding.UTF8.GetBytes("/account/name/:ACC:account"))));
        }
        protected override async Task AddTransaction(long transactionId, byte[] mutationHash, Mutation mutation)
        {
            foreach (Record record in mutation.Records)
            {
                RecordKey key = RecordKey.Parse(record.Key);

                var dbRecord = await Records.Where(r => r.Key == record.Key.ToByteArray()).FirstOrDefaultAsync();

                //TODO: check if dbrecord is null

                dbRecord.Type = key.RecordType;
                dbRecord.Name = key.Name;

                Context.Update(dbRecord);

                await Context.SaveChangesAsync();

                var newMutation = new Models.RecordMutation
                {
                    RecordKey     = record.Key.ToByteArray(),
                    TransactionId = transactionId,
                    MutationHash  = mutationHash
                };

                RecordMutations.Add(newMutation);

                await Context.SaveChangesAsync();
            }
        }
Esempio n. 3
0
        public async Task <ActionResult> GetTransactionsByPath(
            [FromQuery(Name = "path")]
            string path)
        {
            if (!LedgerPath.TryParse(path, out LedgerPath ledgerPath))
            {
                return(BadRequest());
            }

            var directory = LedgerPath.FromSegments(ledgerPath.Segments.ToArray());
            var accounts  = await this.store.GetSubaccounts(directory.FullPath);

            var keys             = accounts.Where(x => RecordKey.Parse(x.Key).RecordType == RecordType.Account).Select(x => x.Key);
            var transactionsData = await this.storageEngine.GetTransactionByRecordKeys(keys, new TransactionFilter());

            var transactions = transactionsData.Select(x => new ExtTransaction(x)).ToList();

            var hashtable = new Hashtable();

            foreach (var transaction in transactions)
            {
                foreach (var record in transaction.Mutation.Records)
                {
                    var val = BitConverter.ToInt64(record.Value.Value.Reverse().ToArray(), 0);
                    hashtable.Add(transaction.MutationHash + record.Key.ToString(), val);
                }
            }

            var res = transactions.Select(x => TransactionToJsonExt(x, hashtable).Value).ToArray();

            return(Json(res));
        }
            public Task <IList <Record> > GetRecords(IEnumerable <ByteString> keys)
            {
                return(Task.FromResult <IList <Record> >(keys.Select(key =>
                {
                    RecordKey recordKey = RecordKey.Parse(key);

                    if (recordKey.Name == "acl")
                    {
                        if (recordKey.Path.FullPath == "/root/subitem/")
                        {
                            return new Record(key, GetValidAcl(), ByteString.Empty);
                        }
                        else if (recordKey.Path.FullPath == "/root/invalid/")
                        {
                            return new Record(key, GetInvalidAcl(), ByteString.Empty);
                        }
                        else if (recordKey.Path.FullPath == "/root/comment/")
                        {
                            return new Record(key, GetCommentedAcl(), ByteString.Empty);
                        }
                    }

                    return new Record(key, ByteString.Empty, ByteString.Empty);
                })
                                                         .ToList()));
            }
Esempio n. 5
0
        protected override async Task AddTransaction(long transactionId, byte[] mutationHash, Mutation mutation)
        {
            foreach (Record record in mutation.Records)
            {
                RecordKey key = RecordKey.Parse(record.Key);

                await ExecuteAsync(@"
                        UPDATE  Records
                        SET     Type = @type,
                                Name = @name
                        WHERE   Key = @key",
                                   new Dictionary <string, object>()
                {
                    ["@key"]  = record.Key.ToByteArray(),
                    ["@type"] = (int)key.RecordType,
                    ["@name"] = key.Name
                });

                await ExecuteAsync(@"
                        INSERT INTO RecordMutations
                        (RecordKey, TransactionId, MutationHash)
                        VALUES (@recordKey, @transactionId, @mutationHash)",
                                   new Dictionary <string, object>()
                {
                    ["@recordKey"]     = record.Key.ToByteArray(),
                    ["@transactionId"] = transactionId,
                    ["@mutationHash"]  = mutationHash
                });
            }
        }
Esempio n. 6
0
        public void Parse_Data()
        {
            ByteString data = new ByteString(Encoding.UTF8.GetBytes("/aka/name/:DATA:record:name"));
            RecordKey  key  = RecordKey.Parse(data);

            Assert.Equal(RecordType.Data, key.RecordType);
            Assert.Equal("/aka/name/", key.Path.FullPath);
            Assert.Equal("record:name", key.Name);
        }
Esempio n. 7
0
        public void Parse_Account()
        {
            ByteString data = new ByteString(Encoding.UTF8.GetBytes("/account/name/:ACC:/asset/name/"));
            RecordKey  key  = RecordKey.Parse(data);

            Assert.Equal(RecordType.Account, key.RecordType);
            Assert.Equal("/account/name/", key.Path.FullPath);
            Assert.Equal("/asset/name/", key.Name);
        }
        protected override MongoDbRecord BuildMongoDbRecord(Record rec)
        {
            RecordKey key = RecordKey.Parse(rec.Key);
            var       r   = new MongoDbRecord {
                Key = rec.Key.ToByteArray(), KeyS = Encoding.UTF8.GetString(rec.Key.ToByteArray()), Value = rec.Value?.ToByteArray(), Version = rec.Version.ToByteArray(), Path = key.Path.Segments.ToArray(), Type = key.RecordType, Name = key.Name
            };

            return(r);
        }
 public Task <IReadOnlyList <Record> > GetRecords(IEnumerable <ByteString> keys)
 {
     return(Task.FromResult <IReadOnlyList <Record> >(keys.Select(key =>
     {
         RecordKey recordKey = RecordKey.Parse(key);
         return new Record(
             key,
             new ByteString(BitConverter.GetBytes(this.accounts[recordKey.Path.FullPath]).Reverse()),
             ByteString.Empty);
     })
                                                      .ToList()));
 }
Esempio n. 10
0
        private object RecordToJson(Record record, string key, Hashtable hashtable)
        {
            var value   = BitConverter.ToInt64(record.Value.Value.Reverse().ToArray(), 0);
            var prevVal = hashtable.ContainsKey(key) ? (long)hashtable[key] : 0;

            return(new
            {
                key = RecordKey.Parse(record.Key),
                value = value,
                version = record.Version.ToString(),
                delta = value - prevVal
            });
        }
Esempio n. 11
0
        public static ParsedMutation Parse(Mutation mutation)
        {
            List <AccountStatus> accountMutations = new List <AccountStatus>();
            List <KeyValuePair <RecordKey, ByteString> > dataRecords = new List <KeyValuePair <RecordKey, ByteString> >();

            foreach (Record record in mutation.Records)
            {
                // This is used for optimistic concurrency and does not participate in the validation
                if (record.Value == null)
                {
                    continue;
                }

                try
                {
                    RecordKey key = RecordKey.Parse(record.Key);
                    switch (key.RecordType)
                    {
                    case RecordType.Account:
                        accountMutations.Add(AccountStatus.FromRecord(key, record));
                        break;

                    case RecordType.Data:
                        dataRecords.Add(new KeyValuePair <RecordKey, ByteString>(key, record.Value));
                        break;
                    }
                }
                catch (ArgumentOutOfRangeException ex) when(ex.ParamName == "keyData")
                {
                    // Deserializing and re-serializing the record gives a different result
                    throw new TransactionInvalidException("NonCanonicalSerialization");
                }
                catch (ArgumentOutOfRangeException ex) when(ex.ParamName == "path")
                {
                    // The path is invalid
                    throw new TransactionInvalidException("InvalidPath");
                }
                catch (ArgumentOutOfRangeException ex) when(ex.ParamName == "recordType")
                {
                    // The specified record type is unknown
                    throw new TransactionInvalidException("InvalidRecord");
                }
                catch (ArgumentOutOfRangeException ex) when(ex.ParamName == "record")
                {
                    // The value of an ACC record could not be deserialized
                    throw new TransactionInvalidException("InvalidRecord");
                }
            }

            return(new ParsedMutation(accountMutations, dataRecords));
        }
        public void FromRecord_Set()
        {
            Record record = new Record(
                AccountKey.Parse("/the/account/", "/the/asset/").Key.ToBinary(),
                SerializeInt(100),
                binaryData[1]);

            AccountStatus status = AccountStatus.FromRecord(RecordKey.Parse(record.Key), record);

            Assert.Equal("/the/account/", status.AccountKey.Account.FullPath);
            Assert.Equal("/the/asset/", status.AccountKey.Asset.FullPath);
            Assert.Equal(100, status.Balance);
            Assert.Equal(binaryData[1], status.Version);
        }
        public void FromRecord_Unset()
        {
            Record record = new Record(
                AccountKey.Parse("/the/account/", "/the/asset/").Key.ToBinary(),
                ByteString.Empty,
                binaryData[1]);

            AccountStatus status = AccountStatus.FromRecord(RecordKey.Parse(record.Key), record);

            Assert.Equal("/the/account/", status.AccountKey.Account.FullPath);
            Assert.Equal("/the/asset/", status.AccountKey.Asset.FullPath);
            Assert.Equal(0, status.Balance);
            Assert.Equal(binaryData[1], status.Version);
        }
        public async Task <IList <OutboundTransaction> > GetUnprocessedTransactions()
        {
            string account = $"/asset/{assetName}/out/";
            string asset   = $"/asset/{assetName}/";

            HttpClient          client           = new HttpClient();
            HttpResponseMessage accountsResponse = await client.GetAsync(new Uri(tedChainUri, $"query/subaccounts?account={account}"));

            JArray records = JArray.Parse(await accountsResponse.EnsureSuccessStatusCode().Content.ReadAsStringAsync());

            List <OutboundTransaction> result = new List <OutboundTransaction>();

            foreach (JObject record in records)
            {
                ByteString mutationHash = ByteString.Parse((string)record["version"]);
                ByteString key          = ByteString.Parse((string)record["key"]);
                RecordKey  recordKey    = RecordKey.Parse(key);

                if (recordKey.RecordType != RecordType.Account || recordKey.Name != $"/asset/{assetName}/")
                {
                    continue;
                }

                HttpResponseMessage transactionResponse = await client.GetAsync(new Uri(tedChainUri, $"query/transaction?mutation_hash={mutationHash}"));

                JObject rawTransaction = JObject.Parse(await transactionResponse.EnsureSuccessStatusCode().Content.ReadAsStringAsync());

                Transaction transaction = MessageSerializer.DeserializeTransaction(ByteString.Parse((string)rawTransaction["raw"]));
                Mutation    mutation    = MessageSerializer.DeserializeMutation(transaction.Mutation);

                // TODO: Validate that the record mutation has an empty version

                string target = GetPayingAddress(mutation);
                if (target != null)
                {
                    long value = ParseInt(ByteString.Parse((string)record["value"]));

                    result.Add(new OutboundTransaction(key, value, mutationHash, target));
                }
            }

            return(result);
        }
Esempio n. 15
0
        public async Task GetAllRecords_Success()
        {
            await AddRecords("/a/:DATA:name1");
            await AddRecords("/b/:DATA:name2");
            await AddRecords("/c/:DATA:name3");
            await AddRecords("/d/:DATA:name3");
            await AddRecords("/e/:DATA:/path/1/");
            await AddRecords("/f/:ACC:/path/1/");
            await AddRecords("/g/:ACC:/path/2/");

            IReadOnlyList <Record> result1 = await Indexes.GetAllRecords(RecordType.Data, "/path/1/");

            IReadOnlyList <Record> result2 = await Indexes.GetAllRecords(RecordType.Data, "name3");

            IReadOnlyList <Record> result3 = await Indexes.GetAllRecords(RecordType.Account, "/path/1/");

            Assert.Equal(1, result1.Count);
            Assert.Equal("/e/", RecordKey.Parse(result1[0].Key).Path.FullPath);
            Assert.Equal(2, result2.Count);
            Assert.Equal("/c/", RecordKey.Parse(result2[0].Key).Path.FullPath);
            Assert.Equal("/d/", RecordKey.Parse(result2[1].Key).Path.FullPath);
            Assert.Equal(1, result3.Count);
            Assert.Equal("/f/", RecordKey.Parse(result3[0].Key).Path.FullPath);
        }
Esempio n. 16
0
        public async Task <ActionResult> GetFilteredTransactions()
        {
            string            path;
            TransactionFilter filter;
            JObject           body;

            try
            {
                string bodyContent;
                using (StreamReader streamReader = new StreamReader(Request.Body))
                    bodyContent = await streamReader.ReadToEndAsync();

                body = JObject.Parse(bodyContent);
                path = body["path"].ToString();
                var jFilter = (JObject)body["filter"];
                filter = new TransactionFilter()
                {
                    StartDate = (DateTime)jFilter["start"],
                    EndDate   = (DateTime)jFilter["end"]
                };
            }
            catch (JsonReaderException)
            {
                return(BadRequest());
            }


            if (!LedgerPath.TryParse(path, out LedgerPath ledgerPath))
            {
                return(BadRequest());
            }

            var directory = LedgerPath.FromSegments(ledgerPath.Segments.ToArray());
            var accounts  = await this.store.GetSubaccounts(directory.FullPath);

            var keys = accounts.Where(x => RecordKey.Parse(x.Key).RecordType == RecordType.Account).Select(x => x.Key);

            var transactionsData = await this.storageEngine.GetTransactionByRecordKeys(keys, filter);

            var transactions = transactionsData.Select(x => new ExtTransaction(x)).ToList();

            var hash = new List <ByteString>();

            foreach (var transaction in transactions)
            {
                hash.AddRange(transaction.Mutation.Records.Select(x => x.Version));
            }

            var prevTransactionsData = await this.storageEngine.GetTransactionsByMutationHash(hash.Distinct());

            var prevTransactions = prevTransactionsData.Select(x => new ExtTransaction(x)).ToList();

            var hashtable = new Hashtable();

            foreach (var transaction in prevTransactions)
            {
                foreach (var record in transaction.Mutation.Records)
                {
                    var val = BitConverter.ToInt64(record.Value.Value.Reverse().ToArray(), 0);
                    hashtable.Add(transaction.MutationHash + record.Key.ToString(), val);
                }
            }

            var res = transactions.Select(x => TransactionToJsonExt(x, hashtable).Value).ToArray();

            return(Json(res));
        }
Esempio n. 17
0
 protected override RecordKey ParseRecordKey(ByteString key)
 {
     return(RecordKey.Parse(key));
 }