public Task<PermissionSet> GetPermissions(IReadOnlyList<SignatureEvidence> authentication, LedgerPath path, bool recursiveOnly, string recordName) { HashSet<string> identities = new HashSet<string>(authentication.Select(evidence => keyEncoder.GetPubKeyHash(evidence.PublicKey)), StringComparer.Ordinal); LedgerPath pathRecordName; // If the path is root and the record name is a tird-party asset owned by the current identity, // arbitrary modification of the balance is allowed if (LedgerPath.TryParse(recordName, out pathRecordName) && thirdPartyAssetPath.IsStrictParentOf(pathRecordName) && path.Segments.Count == 0 && identities.Contains(pathRecordName.Segments[thirdPartyAssetPath.Segments.Count])) { return Task.FromResult(new PermissionSet(accountNegative: Access.Permit)); } // Account /asset/p2pkh/[addr]/ if (thirdPartyAssetPath.IsStrictParentOf(path) && path.Segments.Count == thirdPartyAssetPath.Segments.Count + 1 && keyEncoder.IsP2pkh(path.Segments[path.Segments.Count - 1])) { Access ownAccount = identities.Contains(path.Segments[path.Segments.Count - 1]) && recordName != DynamicPermissionLayout.AclResourceName ? Access.Permit : Access.Unset; return Task.FromResult(new PermissionSet( accountModify: Access.Permit, accountSpend: ownAccount, dataModify: ownAccount)); } else { return Task.FromResult(new PermissionSet()); } }
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}"); }
public async Task <ActionResult> GetRecordsByName( [FromQuery(Name = "name")] string recordName, [FromQuery(Name = "type")] string recordType) { if (recordName == null) { return(BadRequest()); } RecordKey record; try { record = RecordKey.ParseRecord(recordType, LedgerPath.FromSegments(), recordName); } catch (ArgumentOutOfRangeException) { return(BadRequest()); } IReadOnlyList <Record> records = await this.indexes.GetAllRecords(record.RecordType, record.Name); return(Json(records.Select(GetRecordJson).ToArray())); }
public Task Initialize(IServiceProvider serviceProvider, IConfigurationSection configuration) { byte versionByte = byte.Parse(configuration["version_byte"]); this.keyEncoder = new KeyEncoder(versionByte); P2pkhSubject[] adminAddresses = configuration .GetSection("admin_addresses") .GetChildren() .Select(key => key.Value) .Select(address => new P2pkhSubject(new[] { address }, 1, keyEncoder)) .ToArray(); List <Acl> pathPermissions = new List <Acl>() { // Admins have full rights new Acl(adminAddresses, LedgerPath.Parse("/"), true, StringPattern.MatchAll, PermissionSet.AllowAll) }; if (bool.Parse(configuration["allow_third_party_assets"])) { this.staticPermissionProviders.Add(new P2pkhIssuanceImplicitLayout(keyEncoder)); } if (bool.Parse(configuration["allow_p2pkh_accounts"])) { this.staticPermissionProviders.Add(new P2pkhImplicitLayout(keyEncoder)); } this.staticPermissionProviders.Add(new StaticPermissionLayout(pathPermissions)); return(Task.FromResult(0)); }
/// <summary> /// Checks if the given parameters constitute a match for this <see cref="Acl"/> object. /// </summary> /// <param name="authentication">The signatures available.</param> /// <param name="path">The path of the record being tested.</param> /// <param name="recursiveOnly">Whether this object must be a recursive permission.</param> /// <param name="recordName">The name of the record being tested.</param> /// <returns>A boolean indicating whether the given parameters match.</returns> public bool IsMatch(IReadOnlyList <SignatureEvidence> authentication, LedgerPath path, bool recursiveOnly, string recordName) { return(Path.FullPath == path.FullPath && (!recursiveOnly || Recursive) && RecordName.IsMatch(recordName) && Subjects.Any(subject => subject.IsMatch(authentication))); }
public Task <PermissionSet> GetPermissions(IReadOnlyList <SignatureEvidence> authentication, LedgerPath path, bool recursiveOnly, string recordName) { HashSet <string> identities = new HashSet <string>(authentication.Select(evidence => keyEncoder.GetPubKeyHash(evidence.PublicKey)), StringComparer.Ordinal); LedgerPath pathRecordName; // If the path is root and the record name is a tird-party asset owned by the current identity, // arbitrary modification of the balance is allowed if (LedgerPath.TryParse(recordName, out pathRecordName) && thirdPartyAssetPath.IsStrictParentOf(pathRecordName) && path.Segments.Count == 0 && identities.Contains(pathRecordName.Segments[thirdPartyAssetPath.Segments.Count])) { return(Task.FromResult(new PermissionSet(accountNegative: Access.Permit))); } // Account /asset/p2pkh/[addr]/ if (thirdPartyAssetPath.IsStrictParentOf(path) && path.Segments.Count == thirdPartyAssetPath.Segments.Count + 1 && keyEncoder.IsP2pkh(path.Segments[path.Segments.Count - 1])) { Access ownAccount = identities.Contains(path.Segments[path.Segments.Count - 1]) && recordName != DynamicPermissionLayout.AclResourceName ? Access.Permit : Access.Unset; return(Task.FromResult(new PermissionSet( accountModify: Access.Permit, accountCreate: Access.Permit, accountSpend: ownAccount, dataModify: ownAccount))); } else { return(Task.FromResult(new PermissionSet())); } }
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 async Task<PermissionSet> GetPermissions(IReadOnlyList<SignatureEvidence> identities, LedgerPath path, bool recursiveOnly, string recordName) { PermissionSet currentPermissions = PermissionSet.Unset; Record record = await this.store.GetRecord(new RecordKey(RecordType.Data, path, AclResourceName)); if (record.Value.Value.Count == 0) return PermissionSet.Unset; IReadOnlyList<Acl> permissions; try { permissions = Acl.Parse(Encoding.UTF8.GetString(record.Value.ToByteArray()), path, keyEncoder); } catch (JsonReaderException) { return PermissionSet.Unset; } catch (InvalidOperationException) { return PermissionSet.Unset; } foreach (Acl acl in permissions) { if (acl.IsMatch(identities, path, recursiveOnly, recordName)) currentPermissions = currentPermissions.Add(acl.Permissions); } return currentPermissions; }
public void TryParse_Success() { // Normal case LedgerPath path; bool result = LedgerPath.TryParse("/abc/def/", out path); Assert.Equal(true, result); Assert.Equal("/abc/def/", path.FullPath); Assert.Equal <string>(new[] { "abc", "def" }, path.Segments); // All characters result = LedgerPath.TryParse("/azAZ0189$-_.+!*'(),/", out path); Assert.Equal(true, result); Assert.Equal("/azAZ0189$-_.+!*'(),/", path.FullPath); Assert.Equal <string>(new[] { "azAZ0189$-_.+!*'()," }, path.Segments); // Directory result = LedgerPath.TryParse("/abc/def/", out path); Assert.Equal(true, result); Assert.Equal("/abc/def/", path.FullPath); Assert.Equal <string>(new[] { "abc", "def" }, path.Segments); // Root result = LedgerPath.TryParse("/", out path); Assert.Equal(true, result); Assert.Equal("/", path.FullPath); Assert.Equal <string>(new string[] { }, path.Segments); }
public void AccountKey_Success() { AccountKey result = new AccountKey(LedgerPath.Parse("/path/"), LedgerPath.Parse("/asset/")); Assert.Equal("/path/", result.Account.FullPath); Assert.Equal("/asset/", result.Asset.FullPath); }
public void TryParse_Invalid(string value) { LedgerPath path; bool result = LedgerPath.TryParse(value, out path); Assert.Equal(false, result); Assert.Equal(null, path); }
async Task <long> GetAccountBalance(string account, string asset) { var lAsset = LedgerPath.Parse(asset); var aFrom = new AccountKey(LedgerPath.Parse(account), lAsset); var r = await Engine.GetAccounts(new[] { aFrom }); return(r[aFrom].Balance); }
public async Task GetPermissions_NoMatch() { DynamicPermissionLayout layout = new DynamicPermissionLayout(new TestStore(), new KeyEncoder(111)); PermissionSet result = await layout.GetPermissions(evidence, LedgerPath.Parse("/root/subitem/"), true, "other"); AssertPermissionSet(Access.Unset, result); }
public async Task GetPermissions_JsonComments() { DynamicPermissionLayout layout = new DynamicPermissionLayout(new TestStore(), new KeyEncoder(111)); PermissionSet result = await layout.GetPermissions(evidence, LedgerPath.Parse("/root/comment/"), true, "name"); AssertPermissionSet(Access.Unset, result); }
public void FromRecord_InvalidRecordType() { RecordKey key = new RecordKey(RecordType.Data, LedgerPath.Parse("/path/"), "name"); Record record = new Record(key.ToBinary(), ByteString.Empty, binaryData[1]); ArgumentOutOfRangeException exception = Assert.Throws <ArgumentOutOfRangeException>(() => AccountStatus.FromRecord(key, record)); Assert.Equal("key", exception.ParamName); }
public void AccountKey_ArgumentNullException() { ArgumentNullException exception; exception = Assert.Throws <ArgumentNullException>(() => new AccountKey(null, LedgerPath.Parse("/asset/"))); Assert.Equal("account", exception.ParamName); exception = Assert.Throws <ArgumentNullException>(() => new AccountKey(LedgerPath.Parse("/path/"), null)); Assert.Equal("asset", exception.ParamName); }
public void IsParentOf_Success() { LedgerPath parent = LedgerPath.Parse("/the/parent/"); Assert.True(parent.IsParentOf(LedgerPath.Parse("/the/parent/child/"))); Assert.True(parent.IsParentOf(LedgerPath.Parse("/the/parent/child/child/"))); Assert.True(parent.IsParentOf(LedgerPath.Parse("/the/parent/"))); Assert.False(parent.IsParentOf(LedgerPath.Parse("/the/"))); Assert.False(parent.IsParentOf(LedgerPath.Parse("/not/related/"))); }
public async Task GetPermissions_AclRecord() { P2pkhIssuanceImplicitLayout layout = new P2pkhIssuanceImplicitLayout(new KeyEncoder(111)); PermissionSet result = await layout.GetPermissions(evidence, LedgerPath.Parse($"/asset/p2pkh/{address}/"), true, $"acl"); Assert.Equal(Access.Permit, result.AccountModify); Assert.Equal(Access.Unset, result.AccountNegative); Assert.Equal(Access.Unset, result.AccountSpend); Assert.Equal(Access.Unset, result.DataModify); }
public async Task GetPermissions_Modify() { P2pkhIssuanceImplicitLayout layout = new P2pkhIssuanceImplicitLayout(new KeyEncoder(111)); PermissionSet result = await layout.GetPermissions(evidence, LedgerPath.Parse($"/asset/p2pkh/mgToXgKQqY3asA76uYU82BXMLGrHNm5ZD9/"), true, $"/asset-path/"); Assert.Equal(Access.Permit, result.AccountModify); Assert.Equal(Access.Unset, result.AccountNegative); Assert.Equal(Access.Unset, result.AccountSpend); Assert.Equal(Access.Unset, result.DataModify); }
public async Task GetPermissions_NoPermissions(string value) { P2pkhIssuanceImplicitLayout layout = new P2pkhIssuanceImplicitLayout(new KeyEncoder(111)); PermissionSet result = await layout.GetPermissions(evidence, LedgerPath.Parse(value), true, $"/asset-path/"); Assert.Equal(Access.Unset, result.AccountModify); Assert.Equal(Access.Unset, result.AccountNegative); Assert.Equal(Access.Unset, result.AccountSpend); Assert.Equal(Access.Unset, result.DataModify); }
public async Task GetPermissions_JsonComments() { DynamicPermissionLayout layout = new DynamicPermissionLayout(new TestStore(), new KeyEncoder(111)); PermissionSet result = await layout.GetPermissions(evidence, LedgerPath.Parse("/root/comment/"), true, "name"); Assert.Equal(Access.Unset, result.AccountModify); Assert.Equal(Access.Unset, result.AccountNegative); Assert.Equal(Access.Unset, result.AccountSpend); Assert.Equal(Access.Unset, result.DataModify); }
public Task<PermissionSet> GetPermissions(IReadOnlyList<SignatureEvidence> authentication, LedgerPath path, bool recursiveOnly, string recordName) { PermissionSet currentPermissions = PermissionSet.Unset; foreach (Acl acl in permissions) { if (acl.IsMatch(authentication, path, recursiveOnly, recordName)) currentPermissions = currentPermissions.Add(acl.Permissions); } return Task.FromResult(currentPermissions); }
public PermitAllValidatorBuilder() { P2pkhSubject subject = new P2pkhSubject(new string[0], 0, new KeyEncoder(0)); List <Acl> permissions = new List <Acl>() { new Acl(new IPermissionSubject[] { subject }, LedgerPath.Parse("/"), true, StringPattern.MatchAll, PermissionSet.AllowAll) }; StaticPermissionLayout layout = new StaticPermissionLayout(permissions); this.validator = new PermissionBasedValidator(new[] { layout }); }
public Acl( IEnumerable <IPermissionSubject> subjects, LedgerPath path, bool recursive, StringPattern recordName, PermissionSet permissions) { this.Subjects = subjects.ToList().AsReadOnly(); this.Path = path; this.Recursive = recursive; this.RecordName = recordName; this.Permissions = permissions; }
public void FromSegments_ArgumentOutOfRangeException() { ArgumentOutOfRangeException exception; exception = Assert.Throws <ArgumentOutOfRangeException>(() => LedgerPath.FromSegments("@")); Assert.Equal("segments", exception.ParamName); exception = Assert.Throws <ArgumentOutOfRangeException>(() => LedgerPath.FromSegments(null)); Assert.Equal("segments", exception.ParamName); exception = Assert.Throws <ArgumentOutOfRangeException>(() => LedgerPath.FromSegments("")); Assert.Equal("segments", exception.ParamName); }
public void TryParse_InvalidCharacter() { const string invalidCharacters = " \"#%&/:;<=>?@[\\]^`{|}~\t\r\n\0é"; foreach (char c in invalidCharacters) { LedgerPath path; bool result = LedgerPath.TryParse("/" + c + "/", out path); Assert.Equal(null, path); Assert.Equal(false, result); Assert.Equal(false, LedgerPath.IsValidPathSegment(c.ToString())); } }
public void Parse_Success() { IReadOnlyList <Acl> result = Acl.Parse(GetValidAcl(), LedgerPath.Parse("/root/path/"), new KeyEncoder(111)); Assert.Equal(1, result.Count); Assert.Equal("/root/path/", result[0].Path.FullPath); Assert.Equal("name", result[0].RecordName.Pattern); Assert.Equal(PatternMatchingStrategy.Exact, result[0].RecordName.MatchingStrategy); Assert.Equal(true, result[0].Recursive); Assert.Equal(1, result[0].Subjects.Count); Assert.Equal(Access.Permit, result[0].Permissions.AccountModify); Assert.Equal(Access.Permit, result[0].Permissions.AccountSpend); Assert.Equal(Access.Permit, result[0].Permissions.AccountModify); Assert.Equal(Access.Permit, result[0].Permissions.DataModify); }
public void Parse_Defaults() { const string acl = @"[{ ""subjects"": [ ], ""permissions"": { } }]"; IReadOnlyList <Acl> result = Acl.Parse(acl, LedgerPath.Parse("/root/path/"), new KeyEncoder(111)); Assert.Equal(1, result.Count); Assert.Equal("", result[0].RecordName.Pattern); Assert.Equal(PatternMatchingStrategy.Prefix, result[0].RecordName.MatchingStrategy); Assert.Equal(true, result[0].Recursive); Assert.Equal(0, result[0].Subjects.Count); Assert.Equal(Access.Unset, result[0].Permissions.AccountModify); Assert.Equal(Access.Unset, result[0].Permissions.AccountSpend); Assert.Equal(Access.Unset, result[0].Permissions.AccountModify); Assert.Equal(Access.Unset, result[0].Permissions.DataModify); }
public void FromSegments_Success() { LedgerPath path = LedgerPath.FromSegments(); Assert.Equal("/", path.FullPath); Assert.Equal <string>(new string[0], path.Segments); path = LedgerPath.FromSegments("a"); Assert.Equal("/a/", path.FullPath); Assert.Equal <string>(new[] { "a" }, path.Segments); path = LedgerPath.FromSegments("a", "b"); Assert.Equal("/a/b/", path.FullPath); Assert.Equal <string>(new[] { "a", "b" }, path.Segments); }
public async Task <ActionResult> GetSubaccounts( [FromQuery(Name = "account")] string account) { LedgerPath path; if (!LedgerPath.TryParse(account, out path)) { return(BadRequest()); } LedgerPath directory = LedgerPath.FromSegments(path.Segments.ToArray()); IReadOnlyList <Record> accounts = await this.store.GetSubaccounts(directory.FullPath); return(Json(accounts.Select(GetRecordJson).ToArray())); }
private async Task<PermissionSet> GetPermissions(IReadOnlyList<SignatureEvidence> signedAddresses, LedgerPath path, string recordName) { PermissionSet accumulativePermissions = PermissionSet.DenyAll; for (int i = 0; i <= path.Segments.Count; i++) { bool recursiveOnly = i != path.Segments.Count; LedgerPath currentPath = LedgerPath.FromSegments(path.Segments.Take(i).ToArray()); PermissionSet[] permissions = await Task.WhenAll(this.permissions.Select(item => item.GetPermissions(signedAddresses, currentPath, recursiveOnly, recordName))); PermissionSet currentLevelPermissions = permissions .Aggregate(PermissionSet.Unset, (previous, current) => previous.Add(current)); accumulativePermissions = accumulativePermissions.AddLevel(currentLevelPermissions); } return accumulativePermissions; }
private async Task <PermissionSet> GetPermissions(IReadOnlyList <SignatureEvidence> signedAddresses, LedgerPath path, string recordName) { PermissionSet accumulativePermissions = PermissionSet.DenyAll; for (int i = 0; i <= path.Segments.Count; i++) { bool recursiveOnly = i != path.Segments.Count; LedgerPath currentPath = LedgerPath.FromSegments(path.Segments.Take(i).ToArray()); PermissionSet[] permissions = await Task.WhenAll(this.permissions.Select(item => item.GetPermissions(signedAddresses, currentPath, recursiveOnly, recordName))); PermissionSet currentLevelPermissions = permissions .Aggregate(PermissionSet.Unset, (previous, current) => previous.Add(current)); accumulativePermissions = accumulativePermissions.AddLevel(currentLevelPermissions); } return(accumulativePermissions); }
/// <summary> /// Parses a permission set from a JSON string. /// </summary> /// <param name="json">The JSON string to parse.</param> /// <param name="path">The path on which these permissions apply.</param> /// <param name="keyEncoder">The key encoder to use in the parsed <see cref="Acl"/> objects.</param> /// <returns>The parsed list of <see cref="Acl"/> objects.</returns> public static IReadOnlyList <Acl> Parse(string json, LedgerPath path, KeyEncoder keyEncoder) { JArray document = JArray.Parse(json); return(((IEnumerable <JToken>)document).Select(root => new Acl( ((JArray)root["subjects"]).Children().Select(subject => new P2pkhSubject(((JArray)subject["addresses"]).Select(key => (string)key), (int)subject["required"], keyEncoder)), path, (bool?)root["recursive"] ?? true, new StringPattern((string)root["record_name"] ?? string.Empty, (PatternMatchingStrategy)Enum.Parse(typeof(PatternMatchingStrategy), (string)root["record_name_matching"] ?? "Prefix")), new PermissionSet( accountNegative: Parse(root["permissions"]["account_negative"]), accountSpend: Parse(root["permissions"]["account_spend"]), accountModify: Parse(root["permissions"]["account_modify"]), dataModify: Parse(root["permissions"]["data_modify"])))) .ToList()); }
private ByteString CreateMutation(ByteString @namespace) { Mutation mutation = new Mutation( @namespace, new Record[] { new Record( new AccountKey(LedgerPath.Parse("/account/1/"), LedgerPath.Parse("/a/")).Key.ToBinary(), new ByteString(BitConverter.GetBytes(100L).Reverse()), ByteString.Empty), new Record( new AccountKey(LedgerPath.Parse("/account/2/"), LedgerPath.Parse("/a/")).Key.ToBinary(), new ByteString(BitConverter.GetBytes(100L).Reverse()), ByteString.Empty), }, ByteString.Empty); return(new ByteString(MessageSerializer.SerializeMutation(mutation))); }
public Task<PermissionSet> GetPermissions(IReadOnlyList<SignatureEvidence> authentication, LedgerPath path, bool recursiveOnly, string recordName) { HashSet<string> identities = new HashSet<string>(authentication.Select(evidence => keyEncoder.GetPubKeyHash(evidence.PublicKey)), StringComparer.Ordinal); // Account /p2pkh/[addr] if (p2pkhAccountPath.IsStrictParentOf(path) && path.Segments.Count == p2pkhAccountPath.Segments.Count + 1 && keyEncoder.IsP2pkh(path.Segments[path.Segments.Count - 1])) { Access ownAccount = identities.Contains(path.Segments[path.Segments.Count - 1]) && recordName != DynamicPermissionLayout.AclResourceName ? Access.Permit : Access.Unset; return Task.FromResult(new PermissionSet( accountModify: Access.Permit, accountSpend: ownAccount, dataModify: ownAccount)); } else { return Task.FromResult(new PermissionSet()); } }
public Task<PermissionSet> GetPermissions(IReadOnlyList<SignatureEvidence> identities, LedgerPath path, bool recursiveOnly, string recordName) { Assert.Equal(identities.Select(ConvertEvidence), expectedIdentities, StringComparer.Ordinal); PermissionSet result; if (!getPermissions.TryGetValue(path.FullPath, out result)) throw new InvalidOperationException(); else return Task.FromResult(result); }