/// <summary> /// Parses a <see cref="ByteString"/> into an instance of a <see cref="RecordKey"/> object. /// </summary> /// <param name="keyData">The <see cref="ByteString"/> to parse.</param> /// <returns>The parsed <see cref="RecordKey"/>.</returns> public static RecordKey Parse(ByteString keyData) { if (keyData == null) { throw new ArgumentNullException(nameof(keyData)); } byte[] key = keyData.ToByteArray(); string[] parts = Encoding.UTF8.GetString(key, 0, key.Length).Split(new[] { ':' }, 3); if (parts.Length != 3) { throw new ArgumentOutOfRangeException(nameof(keyData)); } RecordKey result = ParseRecord( parts[1], LedgerPath.Parse(parts[0]), parts[2]); // The byte representation of reencoded value must match the input if (!result.ToBinary().Equals(keyData)) { throw new ArgumentOutOfRangeException(nameof(keyData)); } return(result); }
public static async Task <IReadOnlyList <AccountStatus> > GetAccount(this ILedgerQueries queries, string account) { ByteString prefix = new ByteString(Encoding.UTF8.GetBytes(account + ":ACC:")); IReadOnlyList <Record> records = await queries.GetKeyStartingFrom(prefix); return(records .Where(record => !record.Value.Equals(ByteString.Empty)) .Select(record => AccountStatus.FromRecord(RecordKey.Parse(record.Key), record)) .ToList() .AsReadOnly()); }
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)); }
/// <summary> /// Creates an instance of the <see cref="AccountStatus"/> class from an unparsed record. /// </summary> /// <param name="key">The key of the record.</param> /// <param name="record">The record to create the object from.</param> /// <returns>A new instance of the <see cref="AccountStatus"/> class.</returns> public static AccountStatus FromRecord(RecordKey key, Record record) { if (key.RecordType != RecordType.Account) throw new ArgumentOutOfRangeException(nameof(key)); long amount; if (record.Value.Value.Count == 0) amount = 0; else if (record.Value.Value.Count == 8) amount = BitConverter.ToInt64(record.Value.Value.Reverse().ToArray(), 0); else throw new ArgumentOutOfRangeException(nameof(record)); return new AccountStatus(new AccountKey(key.Path, LedgerPath.Parse(key.Name)), amount, record.Version); }
/// <summary> /// Creates an instance of the <see cref="AccountStatus"/> class from an unparsed record. /// </summary> /// <param name="key">The key of the record.</param> /// <param name="record">The record to create the object from.</param> /// <returns>A new instance of the <see cref="AccountStatus"/> class.</returns> public static AccountStatus FromRecord(RecordKey key, Record record) { if (key.RecordType != RecordType.Account) { throw new ArgumentOutOfRangeException(nameof(key)); } long amount; if (record.Value.Value.Count == 0) { amount = 0; } else if (record.Value.Value.Count == 8) { amount = BitConverter.ToInt64(record.Value.Value.Reverse().ToArray(), 0); } else { throw new ArgumentOutOfRangeException(nameof(record)); } return(new AccountStatus(new AccountKey(key.Path, LedgerPath.Parse(key.Name)), amount, record.Version)); }
public static async Task <IReadOnlyDictionary <AccountKey, AccountStatus> > GetAccounts(this IStorageEngine store, IEnumerable <AccountKey> accounts) { IReadOnlyList <Record> records = await store.GetRecords(accounts.Select(account => account.Key.ToBinary())); return(records.Select(record => AccountStatus.FromRecord(RecordKey.Parse(record.Key), record)).ToDictionary(account => account.AccountKey, account => account)); }
public static async Task <Record> GetRecord(this IStorageEngine store, RecordKey key) { IReadOnlyList <Record> result = await store.GetRecords(new[] { key.ToBinary() }); return(result[0]); }
public static async Task<Record> GetRecord(this IStorageEngine store, RecordKey key) { IReadOnlyList<Record> result = await store.GetRecords(new[] { key.ToBinary() }); return result[0]; }