Skip to content

Commit

Permalink
Resolve implicit access rules requirements (#826)
Browse files Browse the repository at this point in the history
  • Loading branch information
PawelPawelec-RDX authored Feb 14, 2025
1 parent 9940885 commit fa299cd
Show file tree
Hide file tree
Showing 97 changed files with 6,748 additions and 751 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Release built: _not released yet_
- `/extensions/entities-by-role-requirement/page` – allows querying and paginating by a single requirement.
- The `manifest_classes` of the transaction manifest in the `/stream/transactions` endpoint have been adjusted slightly. Notably:
- The `General` classification has been expanded to permit validator stake/unstake/claim actions and pool contribute and redeem actions.
- Added a new endpoint `/extensions/implicit-requirements/lookup` for resolving implicit access rule requirements (https://docs.radixdlt.com/docs/advanced-accessrules#implicit-requirements).

### Database changes
- New entries added to the `ledger_transaction_markers` table for each resource whose balance (excluding fee-related changes) was modified in a transaction. Each resource balance change will be represented by an entry with the `resource_balance_change` discriminator and the resource's `entity_id`.
Expand All @@ -22,9 +23,12 @@ Release built: _not released yet_
- New `outer_object_entity_id` column in the `entities` table, which holds the outer object entity id (e.g resource entity id for vaults and consensus manager entity id for validators).
- New `receipt_event_emitter_entity_ids` column in the `ledger_transaction_events` table, which holds the emitter entity ids for transaction events.
- Added a new `entities_by_role_requirement_entry_definition` table that stores information about entities that have ever used a requirement (resource or non-fungible global ID) in their access rules.
- Added a new `implicit_requirements` table to store data necessary for resolving implicit access rule requirements.

### What’s new?
- Added a new configuration parameter, `GatewayApi__Endpoint__EntitiesByRoleRequirementLookupMaxRequestedRequirementsCount`, which sets the limit (default `50`) on the number of requirements that can be queried using the `/extensions/entities-by-role-requirement/lookup` endpoint.
- Added a new configuration parameter, `GatewayApi__Endpoint__ImplicitRequirementsLookupMaxRequestedRequirementsCount`, which sets the limit (default `100`) on the number of implicit requirements that can be queried using the `/extensions/implicit-requirements/lookup` endpoint.


## 1.9.2
Release built: 9.12.2024
Expand Down
1 change: 0 additions & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" />
<PackageVersion Include="Microsoft.OpenApi.Readers" Version="1.6.13" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="Nito.AsyncEx.Coordination" Version="5.1.2" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.2" />
<PackageVersion Include="Polly" Version="8.3.0" />
<PackageVersion Include="prometheus-net" Version="8.2.1" />
Expand Down
32 changes: 0 additions & 32 deletions apps/DataAggregator/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -458,27 +458,6 @@
"Newtonsoft.Json": "12.0.1"
}
},
"Nito.AsyncEx.Tasks": {
"type": "Transitive",
"resolved": "5.1.2",
"contentHash": "jEkCfR2/M26OK/U4G7SEN063EU/F4LiVA06TtpZILMdX/quIHCg+wn31Zerl2LC+u1cyFancjTY3cNAr2/89PA==",
"dependencies": {
"Nito.Disposables": "2.2.1"
}
},
"Nito.Collections.Deque": {
"type": "Transitive",
"resolved": "1.1.1",
"contentHash": "CU0/Iuv5VDynK8I8pDLwkgF0rZhbQoZahtodfL0M3x2gFkpBRApKs8RyMyNlAi1mwExE4gsmqQXk4aFVvW9a4Q=="
},
"Nito.Disposables": {
"type": "Transitive",
"resolved": "2.2.1",
"contentHash": "6sZ5uynQeAE9dPWBQGKebNmxbY4xsvcc5VplB5WkYEESUS7oy4AwnFp0FhqxTSKm/PaFrFqLrYr696CYN8cugg==",
"dependencies": {
"System.Collections.Immutable": "1.7.1"
}
},
"Npgsql": {
"type": "Transitive",
"resolved": "8.0.2",
Expand Down Expand Up @@ -635,7 +614,6 @@
"Microsoft.Extensions.Hosting": "[8.0.0, )",
"Microsoft.Extensions.Logging.Abstractions": "[8.0.0, )",
"Newtonsoft.Json": "[13.0.3, )",
"Nito.AsyncEx.Coordination": "[5.1.2, )",
"RadixDlt.CoreApiSdk": "[1.10.0-develop, )"
}
},
Expand Down Expand Up @@ -831,16 +809,6 @@
"resolved": "13.0.3",
"contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ=="
},
"Nito.AsyncEx.Coordination": {
"type": "CentralTransitive",
"requested": "[5.1.2, )",
"resolved": "5.1.2",
"contentHash": "QMyUfsaxov//0ZMbOHWr9hJaBFteZd66DV1ay4J5wRODDb8+K/uHC7+3VsOflo6SVw/29mu8OWZp8vMDSuzc0w==",
"dependencies": {
"Nito.AsyncEx.Tasks": "5.1.2",
"Nito.Collections.Deque": "1.1.1"
}
},
"Npgsql.EntityFrameworkCore.PostgreSQL": {
"type": "CentralTransitive",
"requested": "[8.0.2, )",
Expand Down
32 changes: 0 additions & 32 deletions apps/DatabaseMigrations/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -391,27 +391,6 @@
"System.CodeDom": "4.4.0"
}
},
"Nito.AsyncEx.Tasks": {
"type": "Transitive",
"resolved": "5.1.2",
"contentHash": "jEkCfR2/M26OK/U4G7SEN063EU/F4LiVA06TtpZILMdX/quIHCg+wn31Zerl2LC+u1cyFancjTY3cNAr2/89PA==",
"dependencies": {
"Nito.Disposables": "2.2.1"
}
},
"Nito.Collections.Deque": {
"type": "Transitive",
"resolved": "1.1.1",
"contentHash": "CU0/Iuv5VDynK8I8pDLwkgF0rZhbQoZahtodfL0M3x2gFkpBRApKs8RyMyNlAi1mwExE4gsmqQXk4aFVvW9a4Q=="
},
"Nito.Disposables": {
"type": "Transitive",
"resolved": "2.2.1",
"contentHash": "6sZ5uynQeAE9dPWBQGKebNmxbY4xsvcc5VplB5WkYEESUS7oy4AwnFp0FhqxTSKm/PaFrFqLrYr696CYN8cugg==",
"dependencies": {
"System.Collections.Immutable": "1.7.1"
}
},
"Npgsql": {
"type": "Transitive",
"resolved": "8.0.2",
Expand Down Expand Up @@ -568,7 +547,6 @@
"Microsoft.Extensions.Hosting": "[8.0.0, )",
"Microsoft.Extensions.Logging.Abstractions": "[8.0.0, )",
"Newtonsoft.Json": "[13.0.3, )",
"Nito.AsyncEx.Coordination": "[5.1.2, )",
"RadixDlt.CoreApiSdk": "[1.10.0-develop, )"
}
},
Expand Down Expand Up @@ -756,16 +734,6 @@
"resolved": "13.0.3",
"contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ=="
},
"Nito.AsyncEx.Coordination": {
"type": "CentralTransitive",
"requested": "[5.1.2, )",
"resolved": "5.1.2",
"contentHash": "QMyUfsaxov//0ZMbOHWr9hJaBFteZd66DV1ay4J5wRODDb8+K/uHC7+3VsOflo6SVw/29mu8OWZp8vMDSuzc0w==",
"dependencies": {
"Nito.AsyncEx.Tasks": "5.1.2",
"Nito.Collections.Deque": "1.1.1"
}
},
"Npgsql.EntityFrameworkCore.PostgreSQL": {
"type": "CentralTransitive",
"requested": "[8.0.2, )",
Expand Down
10 changes: 8 additions & 2 deletions apps/GatewayApi/Controllers/ExtensionsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,20 @@ public class ExtensionsController(IExtensionsHandler extensionsHandler) : Contro
}

[HttpPost("entities-by-role-requirement/page")]
public async Task<GatewayModel.EntitiesByRoleRequirementPageResponse> ResourceHoldersPage(GatewayModel.EntitiesByRoleRequirementPageRequest request, CancellationToken token)
public async Task<GatewayModel.EntitiesByRoleRequirementPageResponse> EntitiesByRoleRequirementPage(GatewayModel.EntitiesByRoleRequirementPageRequest request, CancellationToken token)
{
return await extensionsHandler.EntitiesByRoleRequirementPage(request, token);
}

[HttpPost("entities-by-role-requirement/lookup")]
public async Task<GatewayModel.EntitiesByRoleRequirementLookupResponse> ResourceHoldersLookup(GatewayModel.EntitiesByRoleRequirementLookupRequest request, CancellationToken token)
public async Task<GatewayModel.EntitiesByRoleRequirementLookupResponse> EntitiesByRoleRequirementLookup(GatewayModel.EntitiesByRoleRequirementLookupRequest request, CancellationToken token)
{
return await extensionsHandler.EntitiesByRoleRequirementLookup(request, token);
}

[HttpPost("implicit-requirements/lookup")]
public async Task<GatewayModel.ImplicitRequirementsLookupResponse> ImplicitRequirementsLookup(GatewayModel.ImplicitRequirementsLookupRequest request, CancellationToken token)
{
return await extensionsHandler.ImplicitRequirementsLookup(request, token);
}
}
4 changes: 2 additions & 2 deletions apps/GatewayApi/Controllers/StatusController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ public StatusController(IStatusHandler statusHandler, INetworkConfigurationProvi
}

[HttpPost("network-configuration")]
public async Task<GatewayModel.NetworkConfigurationResponse> NetworkConfiguration(CancellationToken token)
public GatewayModel.NetworkConfigurationResponse NetworkConfiguration()
{
var networkConfiguration = await _networkConfigurationProvider.GetNetworkConfiguration(token);
var networkConfiguration = _networkConfigurationProvider.GetNetworkConfiguration();
var wellKnownAddresses = networkConfiguration.WellKnownAddresses;

return new GatewayModel.NetworkConfigurationResponse(
Expand Down
13 changes: 11 additions & 2 deletions apps/GatewayApi/OpenApiDocumentHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,11 @@ public static async Task Handle(
response = OptionalReplace(response, "<network-id>", placeholderReplacements.NetworkId?.ToString());
response = OptionalReplace(response, "<network-name>", placeholderReplacements.NetworkName);
response = OptionalReplace(response, "<sample-preview-transaction-hex>", placeholderReplacements.SamplePreviewTransactionHex);
response = OptionalReplace(response, "<sample-requirement-non-fungible-id>", placeholderReplacements.SampleRequirementNonFungibleId);
response = OptionalReplace(response, "<sample-requirement-resource-address>", placeholderReplacements.SampleRequirementResourceAddress);
response = OptionalReplace(response, "<sample-requirement-non-fungible-id>", placeholderReplacements.SampleRequirementNonFungibleId);
response = OptionalReplace(response, "<sample-implicit-requirement-resource-address>", placeholderReplacements.SampleImplicitRequirementResourceAddress);
response = OptionalReplace(response, "<sample-implicit-requirement-non-fungible-id>", placeholderReplacements.SampleImplicitRequirementNonFungibleId);

await context.Response.WriteAsync(response, Encoding.UTF8, token);
}

Expand Down Expand Up @@ -178,6 +181,10 @@ private class PlaceholderReplacements
public string? SampleRequirementResourceAddress { get; set; }

public string? SampleRequirementNonFungibleId { get; set; }

public string? SampleImplicitRequirementResourceAddress { get; set; }

public string? SampleImplicitRequirementNonFungibleId { get; set; }
}

private static async Task<PlaceholderReplacements> GetPlaceholderReplacementsAsync(
Expand All @@ -186,7 +193,7 @@ private static async Task<PlaceholderReplacements> GetPlaceholderReplacementsAsy
CancellationToken token)
{
var placeholderReplacements = new PlaceholderReplacements();
var networkConfiguration = await networkConfigurationProvider.GetNetworkConfiguration(token);
var networkConfiguration = networkConfigurationProvider.GetNetworkConfiguration();

try
{
Expand All @@ -208,6 +215,8 @@ private static async Task<PlaceholderReplacements> GetPlaceholderReplacementsAsy
placeholderReplacements.CommittedSubintentHash = placeholderData.RandomSubintentHash;
placeholderReplacements.SampleRequirementResourceAddress = placeholderData.RequirementResourceAddress;
placeholderReplacements.SampleRequirementNonFungibleId = placeholderData.RequirementNonFungibleId;
placeholderReplacements.SampleImplicitRequirementResourceAddress = networkConfiguration.WellKnownAddresses.GlobalCallerVirtualBadge;
placeholderReplacements.SampleImplicitRequirementNonFungibleId = placeholderData.SampleImplicitRequirementGlobalCallerEntityHash;
placeholderReplacements.SamplePreviewTransactionHex = GenerateRandomPreviewTransactionHex(networkConfiguration.Id, (ulong?)placeholderData.CurrentEpoch);
}
catch (Exception)
Expand Down
32 changes: 0 additions & 32 deletions apps/GatewayApi/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -490,27 +490,6 @@
"Newtonsoft.Json": "12.0.1"
}
},
"Nito.AsyncEx.Tasks": {
"type": "Transitive",
"resolved": "5.1.2",
"contentHash": "jEkCfR2/M26OK/U4G7SEN063EU/F4LiVA06TtpZILMdX/quIHCg+wn31Zerl2LC+u1cyFancjTY3cNAr2/89PA==",
"dependencies": {
"Nito.Disposables": "2.2.1"
}
},
"Nito.Collections.Deque": {
"type": "Transitive",
"resolved": "1.1.1",
"contentHash": "CU0/Iuv5VDynK8I8pDLwkgF0rZhbQoZahtodfL0M3x2gFkpBRApKs8RyMyNlAi1mwExE4gsmqQXk4aFVvW9a4Q=="
},
"Nito.Disposables": {
"type": "Transitive",
"resolved": "2.2.1",
"contentHash": "6sZ5uynQeAE9dPWBQGKebNmxbY4xsvcc5VplB5WkYEESUS7oy4AwnFp0FhqxTSKm/PaFrFqLrYr696CYN8cugg==",
"dependencies": {
"System.Collections.Immutable": "1.7.1"
}
},
"Npgsql": {
"type": "Transitive",
"resolved": "8.0.2",
Expand Down Expand Up @@ -693,7 +672,6 @@
"Microsoft.Extensions.Hosting": "[8.0.0, )",
"Microsoft.Extensions.Logging.Abstractions": "[8.0.0, )",
"Newtonsoft.Json": "[13.0.3, )",
"Nito.AsyncEx.Coordination": "[5.1.2, )",
"RadixDlt.CoreApiSdk": "[1.10.0-develop, )"
}
},
Expand Down Expand Up @@ -889,16 +867,6 @@
"resolved": "13.0.3",
"contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ=="
},
"Nito.AsyncEx.Coordination": {
"type": "CentralTransitive",
"requested": "[5.1.2, )",
"resolved": "5.1.2",
"contentHash": "QMyUfsaxov//0ZMbOHWr9hJaBFteZd66DV1ay4J5wRODDb8+K/uHC7+3VsOflo6SVw/29mu8OWZp8vMDSuzc0w==",
"dependencies": {
"Nito.AsyncEx.Tasks": "5.1.2",
"Nito.Collections.Deque": "1.1.1"
}
},
"Npgsql.EntityFrameworkCore.PostgreSQL": {
"type": "CentralTransitive",
"requested": "[8.0.2, )",
Expand Down
74 changes: 74 additions & 0 deletions src/RadixDlt.CoreApiSdk/Model/UserLedgerTransactionV2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/* Copyright 2021 Radix Publishing Ltd incorporated in Jersey (Channel Islands).
*
* Licensed under the Radix License, Version 1.0 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the License at:
*
* radixfoundation.org/licenses/LICENSE-v1
*
* The Licensor hereby grants permission for the Canonical version of the Work to be
* published, distributed and used under or by reference to the Licensor’s trademark
* Radix ® and use of any unregistered trade names, logos or get-up.
*
* The Licensor provides the Work (and each Contributor provides its Contributions) on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT,
* MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.
*
* Whilst the Work is capable of being deployed, used and adopted (instantiated) to create
* a distributed ledger it is your responsibility to test and validate the code, together
* with all logic and performance of that code under all foreseeable scenarios.
*
* The Licensor does not make or purport to make and hereby excludes liability for all
* and any representation, warranty or undertaking in any form whatsoever, whether express
* or implied, to any entity or person, including any representation, warranty or
* undertaking, as to the functionality security use, value or other characteristics of
* any distributed ledger nor in respect the functioning or value of any tokens which may
* be created stored or transferred using the Work. The Licensor does not warrant that the
* Work or any use of the Work complies with any law or regulation in any territory where
* it may be implemented or used or that it will be appropriate for any specific purpose.
*
* Neither the licensor nor any current or former employees, officers, directors, partners,
* trustees, representatives, agents, advisors, contractors, or volunteers of the Licensor
* shall be liable for any direct or indirect, special, incidental, consequential or other
* losses of any kind, in tort, contract or otherwise (including but not limited to loss
* of revenue, income or profits, or loss of use or data, or loss of reputation, or loss
* of any economic or other opportunity of whatsoever nature or howsoever arising), arising
* out of or in connection with (without limitation of any use, misuse, of any ledger system
* or use made or its functionality or any performance or operation of any code or protocol
* caused by bugs or programming or logic errors or otherwise);
*
* A. any offer, purchase, holding, use, sale, exchange or transmission of any
* cryptographic keys, tokens or assets created, exchanged, stored or arising from any
* interaction with the Work;
*
* B. any failure in a transmission or loss of any token or assets keys or other digital
* artefacts due to errors in transmission;
*
* C. bugs, hacks, logic errors or faults in the Work or any communication;
*
* D. system software or apparatus including but not limited to losses caused by errors
* in holding or transmitting tokens by any third-party;
*
* E. breaches or failure of security including hacker attacks, loss or disclosure of
* password, loss of private key, unauthorised use or misuse of such passwords or keys;
*
* F. any losses including loss of anticipated savings or other benefits resulting from
* use of the Work or any changes to the Work (however implemented).
*
* You are solely responsible for; testing, validating and evaluation of all operation
* logic, functionality, security and appropriateness of using the Work for any commercial
* or non-commercial purpose and for any reproduction or redistribution by You of the
* Work. You assume all risks associated with Your use of the Work and the exercise of
* permissions under this License.
*/

using System;

namespace RadixDlt.CoreApiSdk.Model;

public partial class UserLedgerTransactionV2
{
private byte[] _payloadBytes;

public byte[] GetPayloadBytes() => _payloadBytes ??= Convert.FromHexString(PayloadHex);
}
Loading

0 comments on commit fa299cd

Please sign in to comment.