Skip to content

Commit fa299cd

Browse files
Resolve implicit access rules requirements (#826)
1 parent 9940885 commit fa299cd

File tree

97 files changed

+6748
-751
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

97 files changed

+6748
-751
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Release built: _not released yet_
1212
- `/extensions/entities-by-role-requirement/page` – allows querying and paginating by a single requirement.
1313
- The `manifest_classes` of the transaction manifest in the `/stream/transactions` endpoint have been adjusted slightly. Notably:
1414
- The `General` classification has been expanded to permit validator stake/unstake/claim actions and pool contribute and redeem actions.
15+
- Added a new endpoint `/extensions/implicit-requirements/lookup` for resolving implicit access rule requirements (https://docs.radixdlt.com/docs/advanced-accessrules#implicit-requirements).
1516

1617
### Database changes
1718
- 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`.
@@ -22,9 +23,12 @@ Release built: _not released yet_
2223
- 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).
2324
- New `receipt_event_emitter_entity_ids` column in the `ledger_transaction_events` table, which holds the emitter entity ids for transaction events.
2425
- 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.
26+
- Added a new `implicit_requirements` table to store data necessary for resolving implicit access rule requirements.
2527

2628
### What’s new?
2729
- 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.
30+
- 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.
31+
2832

2933
## 1.9.2
3034
Release built: 9.12.2024

Directory.Packages.props

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" />
1818
<PackageVersion Include="Microsoft.OpenApi.Readers" Version="1.6.13" />
1919
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
20-
<PackageVersion Include="Nito.AsyncEx.Coordination" Version="5.1.2" />
2120
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.2" />
2221
<PackageVersion Include="Polly" Version="8.3.0" />
2322
<PackageVersion Include="prometheus-net" Version="8.2.1" />

apps/DataAggregator/packages.lock.json

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -458,27 +458,6 @@
458458
"Newtonsoft.Json": "12.0.1"
459459
}
460460
},
461-
"Nito.AsyncEx.Tasks": {
462-
"type": "Transitive",
463-
"resolved": "5.1.2",
464-
"contentHash": "jEkCfR2/M26OK/U4G7SEN063EU/F4LiVA06TtpZILMdX/quIHCg+wn31Zerl2LC+u1cyFancjTY3cNAr2/89PA==",
465-
"dependencies": {
466-
"Nito.Disposables": "2.2.1"
467-
}
468-
},
469-
"Nito.Collections.Deque": {
470-
"type": "Transitive",
471-
"resolved": "1.1.1",
472-
"contentHash": "CU0/Iuv5VDynK8I8pDLwkgF0rZhbQoZahtodfL0M3x2gFkpBRApKs8RyMyNlAi1mwExE4gsmqQXk4aFVvW9a4Q=="
473-
},
474-
"Nito.Disposables": {
475-
"type": "Transitive",
476-
"resolved": "2.2.1",
477-
"contentHash": "6sZ5uynQeAE9dPWBQGKebNmxbY4xsvcc5VplB5WkYEESUS7oy4AwnFp0FhqxTSKm/PaFrFqLrYr696CYN8cugg==",
478-
"dependencies": {
479-
"System.Collections.Immutable": "1.7.1"
480-
}
481-
},
482461
"Npgsql": {
483462
"type": "Transitive",
484463
"resolved": "8.0.2",
@@ -635,7 +614,6 @@
635614
"Microsoft.Extensions.Hosting": "[8.0.0, )",
636615
"Microsoft.Extensions.Logging.Abstractions": "[8.0.0, )",
637616
"Newtonsoft.Json": "[13.0.3, )",
638-
"Nito.AsyncEx.Coordination": "[5.1.2, )",
639617
"RadixDlt.CoreApiSdk": "[1.10.0-develop, )"
640618
}
641619
},
@@ -831,16 +809,6 @@
831809
"resolved": "13.0.3",
832810
"contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ=="
833811
},
834-
"Nito.AsyncEx.Coordination": {
835-
"type": "CentralTransitive",
836-
"requested": "[5.1.2, )",
837-
"resolved": "5.1.2",
838-
"contentHash": "QMyUfsaxov//0ZMbOHWr9hJaBFteZd66DV1ay4J5wRODDb8+K/uHC7+3VsOflo6SVw/29mu8OWZp8vMDSuzc0w==",
839-
"dependencies": {
840-
"Nito.AsyncEx.Tasks": "5.1.2",
841-
"Nito.Collections.Deque": "1.1.1"
842-
}
843-
},
844812
"Npgsql.EntityFrameworkCore.PostgreSQL": {
845813
"type": "CentralTransitive",
846814
"requested": "[8.0.2, )",

apps/DatabaseMigrations/packages.lock.json

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -391,27 +391,6 @@
391391
"System.CodeDom": "4.4.0"
392392
}
393393
},
394-
"Nito.AsyncEx.Tasks": {
395-
"type": "Transitive",
396-
"resolved": "5.1.2",
397-
"contentHash": "jEkCfR2/M26OK/U4G7SEN063EU/F4LiVA06TtpZILMdX/quIHCg+wn31Zerl2LC+u1cyFancjTY3cNAr2/89PA==",
398-
"dependencies": {
399-
"Nito.Disposables": "2.2.1"
400-
}
401-
},
402-
"Nito.Collections.Deque": {
403-
"type": "Transitive",
404-
"resolved": "1.1.1",
405-
"contentHash": "CU0/Iuv5VDynK8I8pDLwkgF0rZhbQoZahtodfL0M3x2gFkpBRApKs8RyMyNlAi1mwExE4gsmqQXk4aFVvW9a4Q=="
406-
},
407-
"Nito.Disposables": {
408-
"type": "Transitive",
409-
"resolved": "2.2.1",
410-
"contentHash": "6sZ5uynQeAE9dPWBQGKebNmxbY4xsvcc5VplB5WkYEESUS7oy4AwnFp0FhqxTSKm/PaFrFqLrYr696CYN8cugg==",
411-
"dependencies": {
412-
"System.Collections.Immutable": "1.7.1"
413-
}
414-
},
415394
"Npgsql": {
416395
"type": "Transitive",
417396
"resolved": "8.0.2",
@@ -568,7 +547,6 @@
568547
"Microsoft.Extensions.Hosting": "[8.0.0, )",
569548
"Microsoft.Extensions.Logging.Abstractions": "[8.0.0, )",
570549
"Newtonsoft.Json": "[13.0.3, )",
571-
"Nito.AsyncEx.Coordination": "[5.1.2, )",
572550
"RadixDlt.CoreApiSdk": "[1.10.0-develop, )"
573551
}
574552
},
@@ -756,16 +734,6 @@
756734
"resolved": "13.0.3",
757735
"contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ=="
758736
},
759-
"Nito.AsyncEx.Coordination": {
760-
"type": "CentralTransitive",
761-
"requested": "[5.1.2, )",
762-
"resolved": "5.1.2",
763-
"contentHash": "QMyUfsaxov//0ZMbOHWr9hJaBFteZd66DV1ay4J5wRODDb8+K/uHC7+3VsOflo6SVw/29mu8OWZp8vMDSuzc0w==",
764-
"dependencies": {
765-
"Nito.AsyncEx.Tasks": "5.1.2",
766-
"Nito.Collections.Deque": "1.1.1"
767-
}
768-
},
769737
"Npgsql.EntityFrameworkCore.PostgreSQL": {
770738
"type": "CentralTransitive",
771739
"requested": "[8.0.2, )",

apps/GatewayApi/Controllers/ExtensionsController.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,20 @@ public class ExtensionsController(IExtensionsHandler extensionsHandler) : Contro
8181
}
8282

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

8989
[HttpPost("entities-by-role-requirement/lookup")]
90-
public async Task<GatewayModel.EntitiesByRoleRequirementLookupResponse> ResourceHoldersLookup(GatewayModel.EntitiesByRoleRequirementLookupRequest request, CancellationToken token)
90+
public async Task<GatewayModel.EntitiesByRoleRequirementLookupResponse> EntitiesByRoleRequirementLookup(GatewayModel.EntitiesByRoleRequirementLookupRequest request, CancellationToken token)
9191
{
9292
return await extensionsHandler.EntitiesByRoleRequirementLookup(request, token);
9393
}
94+
95+
[HttpPost("implicit-requirements/lookup")]
96+
public async Task<GatewayModel.ImplicitRequirementsLookupResponse> ImplicitRequirementsLookup(GatewayModel.ImplicitRequirementsLookupRequest request, CancellationToken token)
97+
{
98+
return await extensionsHandler.ImplicitRequirementsLookup(request, token);
99+
}
94100
}

apps/GatewayApi/Controllers/StatusController.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,9 @@ public StatusController(IStatusHandler statusHandler, INetworkConfigurationProvi
9191
}
9292

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

9999
return new GatewayModel.NetworkConfigurationResponse(

apps/GatewayApi/OpenApiDocumentHandler.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,11 @@ public static async Task Handle(
127127
response = OptionalReplace(response, "<network-id>", placeholderReplacements.NetworkId?.ToString());
128128
response = OptionalReplace(response, "<network-name>", placeholderReplacements.NetworkName);
129129
response = OptionalReplace(response, "<sample-preview-transaction-hex>", placeholderReplacements.SamplePreviewTransactionHex);
130-
response = OptionalReplace(response, "<sample-requirement-non-fungible-id>", placeholderReplacements.SampleRequirementNonFungibleId);
131130
response = OptionalReplace(response, "<sample-requirement-resource-address>", placeholderReplacements.SampleRequirementResourceAddress);
131+
response = OptionalReplace(response, "<sample-requirement-non-fungible-id>", placeholderReplacements.SampleRequirementNonFungibleId);
132+
response = OptionalReplace(response, "<sample-implicit-requirement-resource-address>", placeholderReplacements.SampleImplicitRequirementResourceAddress);
133+
response = OptionalReplace(response, "<sample-implicit-requirement-non-fungible-id>", placeholderReplacements.SampleImplicitRequirementNonFungibleId);
134+
132135
await context.Response.WriteAsync(response, Encoding.UTF8, token);
133136
}
134137

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

180183
public string? SampleRequirementNonFungibleId { get; set; }
184+
185+
public string? SampleImplicitRequirementResourceAddress { get; set; }
186+
187+
public string? SampleImplicitRequirementNonFungibleId { get; set; }
181188
}
182189

183190
private static async Task<PlaceholderReplacements> GetPlaceholderReplacementsAsync(
@@ -186,7 +193,7 @@ private static async Task<PlaceholderReplacements> GetPlaceholderReplacementsAsy
186193
CancellationToken token)
187194
{
188195
var placeholderReplacements = new PlaceholderReplacements();
189-
var networkConfiguration = await networkConfigurationProvider.GetNetworkConfiguration(token);
196+
var networkConfiguration = networkConfigurationProvider.GetNetworkConfiguration();
190197

191198
try
192199
{
@@ -208,6 +215,8 @@ private static async Task<PlaceholderReplacements> GetPlaceholderReplacementsAsy
208215
placeholderReplacements.CommittedSubintentHash = placeholderData.RandomSubintentHash;
209216
placeholderReplacements.SampleRequirementResourceAddress = placeholderData.RequirementResourceAddress;
210217
placeholderReplacements.SampleRequirementNonFungibleId = placeholderData.RequirementNonFungibleId;
218+
placeholderReplacements.SampleImplicitRequirementResourceAddress = networkConfiguration.WellKnownAddresses.GlobalCallerVirtualBadge;
219+
placeholderReplacements.SampleImplicitRequirementNonFungibleId = placeholderData.SampleImplicitRequirementGlobalCallerEntityHash;
211220
placeholderReplacements.SamplePreviewTransactionHex = GenerateRandomPreviewTransactionHex(networkConfiguration.Id, (ulong?)placeholderData.CurrentEpoch);
212221
}
213222
catch (Exception)

apps/GatewayApi/packages.lock.json

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -490,27 +490,6 @@
490490
"Newtonsoft.Json": "12.0.1"
491491
}
492492
},
493-
"Nito.AsyncEx.Tasks": {
494-
"type": "Transitive",
495-
"resolved": "5.1.2",
496-
"contentHash": "jEkCfR2/M26OK/U4G7SEN063EU/F4LiVA06TtpZILMdX/quIHCg+wn31Zerl2LC+u1cyFancjTY3cNAr2/89PA==",
497-
"dependencies": {
498-
"Nito.Disposables": "2.2.1"
499-
}
500-
},
501-
"Nito.Collections.Deque": {
502-
"type": "Transitive",
503-
"resolved": "1.1.1",
504-
"contentHash": "CU0/Iuv5VDynK8I8pDLwkgF0rZhbQoZahtodfL0M3x2gFkpBRApKs8RyMyNlAi1mwExE4gsmqQXk4aFVvW9a4Q=="
505-
},
506-
"Nito.Disposables": {
507-
"type": "Transitive",
508-
"resolved": "2.2.1",
509-
"contentHash": "6sZ5uynQeAE9dPWBQGKebNmxbY4xsvcc5VplB5WkYEESUS7oy4AwnFp0FhqxTSKm/PaFrFqLrYr696CYN8cugg==",
510-
"dependencies": {
511-
"System.Collections.Immutable": "1.7.1"
512-
}
513-
},
514493
"Npgsql": {
515494
"type": "Transitive",
516495
"resolved": "8.0.2",
@@ -693,7 +672,6 @@
693672
"Microsoft.Extensions.Hosting": "[8.0.0, )",
694673
"Microsoft.Extensions.Logging.Abstractions": "[8.0.0, )",
695674
"Newtonsoft.Json": "[13.0.3, )",
696-
"Nito.AsyncEx.Coordination": "[5.1.2, )",
697675
"RadixDlt.CoreApiSdk": "[1.10.0-develop, )"
698676
}
699677
},
@@ -889,16 +867,6 @@
889867
"resolved": "13.0.3",
890868
"contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ=="
891869
},
892-
"Nito.AsyncEx.Coordination": {
893-
"type": "CentralTransitive",
894-
"requested": "[5.1.2, )",
895-
"resolved": "5.1.2",
896-
"contentHash": "QMyUfsaxov//0ZMbOHWr9hJaBFteZd66DV1ay4J5wRODDb8+K/uHC7+3VsOflo6SVw/29mu8OWZp8vMDSuzc0w==",
897-
"dependencies": {
898-
"Nito.AsyncEx.Tasks": "5.1.2",
899-
"Nito.Collections.Deque": "1.1.1"
900-
}
901-
},
902870
"Npgsql.EntityFrameworkCore.PostgreSQL": {
903871
"type": "CentralTransitive",
904872
"requested": "[8.0.2, )",
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/* Copyright 2021 Radix Publishing Ltd incorporated in Jersey (Channel Islands).
2+
*
3+
* Licensed under the Radix License, Version 1.0 (the "License"); you may not use this
4+
* file except in compliance with the License. You may obtain a copy of the License at:
5+
*
6+
* radixfoundation.org/licenses/LICENSE-v1
7+
*
8+
* The Licensor hereby grants permission for the Canonical version of the Work to be
9+
* published, distributed and used under or by reference to the Licensor’s trademark
10+
* Radix ® and use of any unregistered trade names, logos or get-up.
11+
*
12+
* The Licensor provides the Work (and each Contributor provides its Contributions) on an
13+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
14+
* including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT,
15+
* MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.
16+
*
17+
* Whilst the Work is capable of being deployed, used and adopted (instantiated) to create
18+
* a distributed ledger it is your responsibility to test and validate the code, together
19+
* with all logic and performance of that code under all foreseeable scenarios.
20+
*
21+
* The Licensor does not make or purport to make and hereby excludes liability for all
22+
* and any representation, warranty or undertaking in any form whatsoever, whether express
23+
* or implied, to any entity or person, including any representation, warranty or
24+
* undertaking, as to the functionality security use, value or other characteristics of
25+
* any distributed ledger nor in respect the functioning or value of any tokens which may
26+
* be created stored or transferred using the Work. The Licensor does not warrant that the
27+
* Work or any use of the Work complies with any law or regulation in any territory where
28+
* it may be implemented or used or that it will be appropriate for any specific purpose.
29+
*
30+
* Neither the licensor nor any current or former employees, officers, directors, partners,
31+
* trustees, representatives, agents, advisors, contractors, or volunteers of the Licensor
32+
* shall be liable for any direct or indirect, special, incidental, consequential or other
33+
* losses of any kind, in tort, contract or otherwise (including but not limited to loss
34+
* of revenue, income or profits, or loss of use or data, or loss of reputation, or loss
35+
* of any economic or other opportunity of whatsoever nature or howsoever arising), arising
36+
* out of or in connection with (without limitation of any use, misuse, of any ledger system
37+
* or use made or its functionality or any performance or operation of any code or protocol
38+
* caused by bugs or programming or logic errors or otherwise);
39+
*
40+
* A. any offer, purchase, holding, use, sale, exchange or transmission of any
41+
* cryptographic keys, tokens or assets created, exchanged, stored or arising from any
42+
* interaction with the Work;
43+
*
44+
* B. any failure in a transmission or loss of any token or assets keys or other digital
45+
* artefacts due to errors in transmission;
46+
*
47+
* C. bugs, hacks, logic errors or faults in the Work or any communication;
48+
*
49+
* D. system software or apparatus including but not limited to losses caused by errors
50+
* in holding or transmitting tokens by any third-party;
51+
*
52+
* E. breaches or failure of security including hacker attacks, loss or disclosure of
53+
* password, loss of private key, unauthorised use or misuse of such passwords or keys;
54+
*
55+
* F. any losses including loss of anticipated savings or other benefits resulting from
56+
* use of the Work or any changes to the Work (however implemented).
57+
*
58+
* You are solely responsible for; testing, validating and evaluation of all operation
59+
* logic, functionality, security and appropriateness of using the Work for any commercial
60+
* or non-commercial purpose and for any reproduction or redistribution by You of the
61+
* Work. You assume all risks associated with Your use of the Work and the exercise of
62+
* permissions under this License.
63+
*/
64+
65+
using System;
66+
67+
namespace RadixDlt.CoreApiSdk.Model;
68+
69+
public partial class UserLedgerTransactionV2
70+
{
71+
private byte[] _payloadBytes;
72+
73+
public byte[] GetPayloadBytes() => _payloadBytes ??= Convert.FromHexString(PayloadHex);
74+
}

0 commit comments

Comments
 (0)