public void UnregisterExecutionServices(long accountId) { _logger.Info($"[{accountId}]: Stopping services for account"); if (_statePersistencyItems.ContainsKey(accountId)) { StatePersistency persistency = _statePersistencyItems[accountId]; persistency.CancellationTokenSource.Cancel(); persistency.WalletSynchronizer.Dispose(); _statePersistencyItems.Remove(accountId); persistency.TransactionsService = null; persistency.WalletSynchronizer = null; persistency.ClientCryptoService = null; } else if (_utxoPersistencyItems.ContainsKey(accountId)) { UtxoPersistency persistency = _utxoPersistencyItems[accountId]; persistency.CancellationTokenSource.Cancel(); persistency.WalletSynchronizer.Dispose(); _utxoPersistencyItems.Remove(accountId); persistency.TransactionsService = null; persistency.WalletSynchronizer = null; persistency.ClientCryptoService = null; } Clean(accountId); }
public IActionResult ProcessRootIdentityRequest(string issuer, [FromBody] IdentityRequestDto identityRequest) { Account identityProviderAccount = _accountsService.GetByPublicKey(issuer.HexStringToByteArray()); StatePersistency statePersistency = _executionContextManager.ResolveStateExecutionServices(identityProviderAccount.AccountId); Tuple <bool, bool> proceed = VerifyFaceImage(identityRequest.FaceImageContent, identityRequest.RootAttributeContent, issuer); if (proceed.Item1) { byte[] rootAssetId = _assetsService.GenerateAssetId(AttributeType.IdCard, identityRequest.RootAttributeContent); byte[] faceImageAssetId = _assetsService.GenerateAssetId(AttributeType.PassportPhoto, identityRequest.FaceImageContent); ProcessIssuingAssociatedAttributes(identityRequest, statePersistency.TransactionsService, rootAssetId, faceImageAssetId); return(TransferAssetToUtxo(statePersistency.TransactionsService, new ConfidentialAccount { PublicSpendKey = identityRequest.RequesterPublicSpendKey.HexStringToByteArray(), PublicViewKey = identityRequest.RequesterPublicViewKey.HexStringToByteArray() }, rootAssetId)); } else { if (!proceed.Item2) { return(BadRequest(new { Message = $"Failed to find person with ID Card number {identityRequest.RootAttributeContent}" })); } return(BadRequest(new { Message = "Captured face does not match to registered one" })); } }
public IActionResult UpdateEmployee(long accountId, [FromBody] EmployeeDto employee) { _dataAccessService.UpdateSpEmployeeCategory(accountId, employee.EmployeeId, employee.GroupId); StatePersistency statePersistency = _executionContextManager.ResolveStateExecutionServices(accountId); statePersistency.TransactionsService.IssueCancelEmployeeRecord(employee.RegistrationCommitment.HexStringToByteArray()); return(Ok(employee)); }
public IActionResult DeleteAllowedSigner(long spId, long allowedSignerId) { long documentId = _dataAccessService.RemoveSpDocumentAllowedSigner(spId, allowedSignerId); SpDocument document = _dataAccessService.GetSpDocument(spId, documentId); StatePersistency statePersistency = _executionContextManager.ResolveStateExecutionServices(spId); statePersistency.TransactionsService.IssueDocumentRecord(document.Hash.HexStringToByteArray(), document.AllowedSigners.Select(s => s.GroupCommitment.HexStringToByteArray()).ToArray()); return(Ok()); }
public IActionResult AddDocument(long spId, [FromBody] DocumentDto documentDto) { documentDto.DocumentId = _dataAccessService.AddSpDocument(spId, documentDto.DocumentName, documentDto.Hash); SpDocument document = _dataAccessService.GetSpDocument(spId, documentDto.DocumentId); StatePersistency statePersistency = _executionContextManager.ResolveStateExecutionServices(spId); statePersistency.TransactionsService.IssueDocumentRecord(document.Hash.HexStringToByteArray(), document.AllowedSigners?.Select(s => s.GroupCommitment.HexStringToByteArray()).ToArray()); return(Ok(documentDto)); }
public IActionResult DeleteEmployee(long accountId, long employeeId) { SpEmployee spEmployee = _dataAccessService.RemoveSpEmployee(accountId, employeeId); StatePersistency statePersistency = _executionContextManager.ResolveStateExecutionServices(accountId); if (!string.IsNullOrEmpty(spEmployee.RegistrationCommitment)) { statePersistency.TransactionsService.IssueCancelEmployeeRecord(spEmployee.RegistrationCommitment.HexStringToByteArray()); } return(Ok()); }
public IActionResult SendAssetIdNew([FromBody] AttributeTransferDetails attributeTransferDetails) { ulong accountId = ulong.Parse(User.Identity.Name, CultureInfo.InvariantCulture); StatePersistency statePersistency = _executionContextManager.ResolveStateExecutionServices(accountId); return(Ok(statePersistency.TransactionsService.TransferAssetToUtxo(_assetsService.GenerateAssetId(AttributeType.IdCard, attributeTransferDetails.Id), new ConfidentialAccount { PublicSpendKey = attributeTransferDetails.PublicSpendKey.HexStringToByteArray(), PublicViewKey = attributeTransferDetails.PublicViewKey.HexStringToByteArray() }))); }
public IActionResult DeleteAllowedSigner(ulong allowedSignerId) { ulong accountId = ulong.Parse(User.Identity.Name, CultureInfo.InvariantCulture); ulong documentId = _dataAccessService.RemoveSpDocumentAllowedSigner(accountId, allowedSignerId); SpDocument document = _dataAccessService.GetSpDocument(accountId, documentId); StatePersistency statePersistency = _executionContextManager.ResolveStateExecutionServices(accountId); statePersistency.TransactionsService.IssueDocumentRecord(document.Hash.HexStringToByteArray(), document.AllowedSigners.Select(s => s.GroupCommitment.HexStringToByteArray()).ToArray()); return(Ok()); }
public IActionResult AddDocument([FromBody] DocumentDto documentDto) { ulong accountId = ulong.Parse(User.Identity.Name, CultureInfo.InvariantCulture); documentDto.DocumentId = _dataAccessService.AddSpDocument(accountId, documentDto.DocumentName, documentDto.Hash); SpDocument document = _dataAccessService.GetSpDocument(accountId, documentDto.DocumentId); StatePersistency statePersistency = _executionContextManager.ResolveStateExecutionServices(accountId); statePersistency.TransactionsService.IssueDocumentRecord(document.Hash.HexStringToByteArray(), document.AllowedSigners?.Select(s => s.GroupCommitment.HexStringToByteArray()).ToArray()); return(Ok(documentDto)); }
public async Task <IActionResult> AddAllowedSigner(long spId, long documentId, [FromBody] AllowedSignerDto allowedSigner) { byte[] groupAssetId = await _assetsService.GenerateAssetId(AttributesSchemes.ATTR_SCHEME_NAME_EMPLOYEEGROUP, allowedSigner.GroupOwner + allowedSigner.GroupName, allowedSigner.GroupOwner).ConfigureAwait(false); byte[] blindingFactor = ConfidentialAssetsHelper.GetRandomSeed(); byte[] groupCommitment = ConfidentialAssetsHelper.GetAssetCommitment(blindingFactor, groupAssetId); allowedSigner.AllowedSignerId = _dataAccessService.AddSpDocumentAllowedSigner(spId, documentId, allowedSigner.GroupOwner, allowedSigner.GroupName, groupCommitment.ToHexString(), blindingFactor.ToHexString()); SpDocument document = _dataAccessService.GetSpDocument(spId, documentId); StatePersistency statePersistency = _executionContextManager.ResolveStateExecutionServices(spId); statePersistency.TransactionsService.IssueDocumentRecord(document.Hash.HexStringToByteArray(), document.AllowedSigners.Select(s => s.GroupCommitment.HexStringToByteArray()).ToArray()); return(Ok(allowedSigner)); }
public IActionResult CreateIdentity([FromBody] IdentityDto identity) { ulong accountId = ulong.Parse(User.Identity.Name, CultureInfo.InvariantCulture); StatePersistency statePersistency = _executionContextManager.ResolveStateExecutionServices(accountId); Account account = _accountsService.GetById(accountId); byte[] assetId = _assetsService.GenerateAssetId((AttributeType)identity.RootAttribute.AttributeType, identity.RootAttribute.Content); statePersistency.TransactionsService.IssueBlindedAsset(assetId, 0UL.ToByteArray(32), out byte[] originatingCommitment); identity.RootAttribute.OriginatingCommitment = originatingCommitment.ToHexString(); Identity identityDb = _externalDataAccessService.CreateIdentity(accountId, identity.Description, new IdentityAttribute { AttributeType = AttributeType.IdCard, Content = identity.RootAttribute.Content, Subject = ClaimSubject.User, Commitment = originatingCommitment }); identity.Id = identityDb.IdentityId.ToString(CultureInfo.InvariantCulture); string imageContent = null; foreach (var identityAttributeDto in identity.AssociatedAttributes) { IdentityAttribute identityAttribute = new IdentityAttribute { AttributeType = (AttributeType)identityAttributeDto.AttributeType, Content = identityAttributeDto.Content, Subject = ClaimSubject.User }; _externalDataAccessService.AddAssociatedIdentityAttribute(identityDb.IdentityId, ref identityAttribute); if (((AttributeType)identityAttributeDto.AttributeType) == AttributeType.PassportPhoto) { imageContent = identityAttributeDto.Content; } } if (!string.IsNullOrEmpty(identity.RootAttribute.Content) && !string.IsNullOrEmpty(imageContent)) { $"{Request.Scheme}://{Request.Host.ToUriComponent()}/biometric/".AppendPathSegment("RegisterPerson").PostJsonAsync(new BiometricPersonDataDto { Requester = account.PublicSpendKey.ToHexString(), PersonData = identity.RootAttribute.Content, ImageString = imageContent }); } _hubContext.Clients.Group(User.Identity.Name).SendAsync("PushIdentity", identity); return(Ok()); }
async Task <IssuanceDetailsDto> IssueIdpAttributesAsRoot( string issuer, ConfidentialAccount confidentialAccount, Identity identity, IEnumerable <AttributeIssuanceDetails> attributeIssuanceDetails, AccountDescriptor account, StatePersistency statePersistency) { IssuanceDetailsDto issuanceDetails = new IssuanceDetailsDto(); IEnumerable <IdentitiesScheme> identitiesSchemes = _dataAccessService.GetAttributesSchemeByIssuer(issuer, true); var rootAttributeDetails = attributeIssuanceDetails.First(a => a.Definition.IsRoot); byte[] rootAssetId = await _assetsService.GenerateAssetId(rootAttributeDetails.Definition.SchemeName, rootAttributeDetails.Value.Value, issuer).ConfigureAwait(false); IdentityAttribute rootAttribute = identity.Attributes.FirstOrDefault(a => a.AttributeName == rootAttributeDetails.Definition.AttributeName); statePersistency.TransactionsService.IssueBlindedAsset(rootAssetId, 0UL.ToByteArray(32), out byte[] originatingCommitment); _dataAccessService.UpdateIdentityAttributeCommitment(rootAttribute.AttributeId, originatingCommitment); issuanceDetails.AssociatedAttributes = await IssueAssociatedAttributes( attributeIssuanceDetails.Where(a => !a.Definition.IsRoot) .ToDictionary(d => identity.Attributes.First(a => a.AttributeName == d.Definition.AttributeName).AttributeId, d => d), statePersistency.TransactionsService, issuer, rootAssetId).ConfigureAwait(false); var packet = statePersistency.TransactionsService.TransferAssetToUtxo(rootAssetId, confidentialAccount); if (packet == null) { _logger.Error($"[{account.AccountId}]: failed to transfer Root Attribute"); throw new RootAttributeTransferFailedException(); } issuanceDetails.RootAttribute = new IssuanceDetailsDto.IssuanceDetailsRoot { AttributeName = rootAttribute.AttributeName, OriginatingCommitment = packet.SurjectionProof.AssetCommitments[0].ToHexString(), AssetCommitment = packet.TransferredAsset.AssetCommitment.ToHexString(), SurjectionProof = $"{packet.SurjectionProof.Rs.E.ToHexString()}{packet.SurjectionProof.Rs.S[0].ToHexString()}" }; return(issuanceDetails); }
public IActionResult AddAllowedSigner(ulong documentId, [FromBody] AllowedSignerDto allowedSigner) { ulong accountId = ulong.Parse(User.Identity.Name, CultureInfo.InvariantCulture); byte[] groupAssetId = _assetsService.GenerateAssetId(AttributeType.EmployeeGroup, allowedSigner.GroupOwner + allowedSigner.GroupName); byte[] blindingFactor = ConfidentialAssetsHelper.GetRandomSeed(); byte[] groupCommitment = ConfidentialAssetsHelper.GetAssetCommitment(groupAssetId, blindingFactor); allowedSigner.AllowedSignerId = _dataAccessService.AddSpDocumentAllowedSigner(accountId, documentId, allowedSigner.GroupOwner, allowedSigner.GroupName, groupCommitment.ToHexString(), blindingFactor.ToHexString()); SpDocument document = _dataAccessService.GetSpDocument(accountId, documentId); StatePersistency statePersistency = _executionContextManager.ResolveStateExecutionServices(accountId); statePersistency.TransactionsService.IssueDocumentRecord(document.Hash.HexStringToByteArray(), document.AllowedSigners.Select(s => s.GroupCommitment.HexStringToByteArray()).ToArray()); return(Ok(allowedSigner)); }
public void InitializeStateExecutionServices(long accountId, byte[] secretKey, Func <long, IStateTransactionsService, IStateClientCryptoService, CancellationToken, IUpdater> updaterFactory = null) { lock (_statePersistencyItems) { if (_statePersistencyItems.ContainsKey(accountId)) { _logger.Info($"[{accountId}]: Account with id {accountId} already registered at StatePersistency"); return; } _logger.Info($"[{accountId}]: {nameof(InitializeStateExecutionServices)} for account with id {accountId}"); try { IWitnessPackagesProvider packetsProvider = _witnessPackagesProviderRepository.GetInstance(_restApiConfiguration.WitnessProviderName); IStateTransactionsService transactionsService = ActivatorUtilities.CreateInstance <StateTransactionsService>(_serviceProvider); IStateClientCryptoService clientCryptoService = ActivatorUtilities.CreateInstance <StateClientCryptoService>(_serviceProvider); IWalletSynchronizer walletSynchronizer = ActivatorUtilities.CreateInstance <StateWalletSynchronizer>(_serviceProvider); StatePacketsExtractor statePacketsExtractor = ActivatorUtilities.CreateInstance <StatePacketsExtractor>(_serviceProvider); CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); packetsProvider.Initialize(accountId, cancellationTokenSource.Token); clientCryptoService.Initialize(secretKey); transactionsService.AccountId = accountId; ulong lastBlockHeight = AsyncUtil.RunSync(() => _gatewayService.GetLastBlockHeight(ConfidentialAssetsHelper.GetPublicKey(Ed25519.SecretKeyFromSeed(secretKey)))); transactionsService.Initialize(clientCryptoService, lastBlockHeight); transactionsService.PipeOutTransactions.LinkTo(_gatewayService.PipeInTransactions); statePacketsExtractor.Initialize(clientCryptoService); statePacketsExtractor.AccountId = accountId; IUpdater updater = updaterFactory != null?updaterFactory(accountId, transactionsService, clientCryptoService, cancellationTokenSource.Token) : CreateStateUpdater(accountId, transactionsService, clientCryptoService, cancellationTokenSource.Token); walletSynchronizer.Initialize(accountId, clientCryptoService); packetsProvider.PipeOut.LinkTo(statePacketsExtractor.PipeIn); statePacketsExtractor.PipeOutPackets.LinkTo(walletSynchronizer.PipeInPackets); statePacketsExtractor.PipeOutProcessed.LinkTo(walletSynchronizer.PipeInPackage); foreach (var externalUpdater in _externalUpdatersRepository.GetInstances()) { externalUpdater.Initialize(accountId); } walletSynchronizer.PipeOutPackets.LinkTo( new ActionBlock <PacketBase>(async p => { var tasks = new List <Task> { updater.PipeIn.SendAsync(p) }; foreach (var externalUpdater in _externalUpdatersRepository.GetInstances()) { tasks.Add(externalUpdater.PipeIn.SendAsync(p)); } await Task.WhenAll(tasks).ConfigureAwait(false); })); packetsProvider.Start(); var state = new StatePersistency { AccountId = accountId, PacketsProvider = packetsProvider, TransactionsService = transactionsService, PacketsExtractor = statePacketsExtractor, ClientCryptoService = clientCryptoService, WalletSynchronizer = walletSynchronizer, CancellationTokenSource = cancellationTokenSource }; _statePersistencyItems.Add(accountId, state); } catch (Exception ex) { _logger.Error($"[{accountId}]: Failure during {nameof(InitializeStateExecutionServices)} for account with id {accountId}", ex); throw; } } }
public async Task <ActionResult <IEnumerable <AttributeValue> > > IssueIdpAttributes(string issuer, [FromBody] IssueAttributesRequestDTO request) { if (request is null) { throw new ArgumentNullException(nameof(request)); } AccountDescriptor account = _accountsService.GetByPublicKey(issuer.HexStringToByteArray()); StatePersistency statePersistency = _executionContextManager.ResolveStateExecutionServices(account.AccountId); IEnumerable <AttributeDefinition> attributeDefinitions = _dataAccessService.GetAttributesSchemeByIssuer(issuer, true) .Select(a => new AttributeDefinition { SchemeId = a.IdentitiesSchemeId, AttributeName = a.AttributeName, SchemeName = a.AttributeSchemeName, Alias = a.Alias, Description = a.Description, IsActive = a.IsActive, IsRoot = a.CanBeRoot }); if (!attributeDefinitions.Any(a => a.IsRoot)) { throw new NoRootAttributeSchemeDefinedException(issuer); } var issuanceInputDetails = GetValidatedIssuanceDetails(request, attributeDefinitions); Identity identity = CreateIdentityInDb(account, issuanceInputDetails); IssuanceDetailsDto issuanceDetails; if (!string.IsNullOrEmpty(request.PublicSpendKey) && !string.IsNullOrEmpty(request.PublicViewKey)) { ConfidentialAccount targetAccount = new ConfidentialAccount { PublicSpendKey = request.PublicSpendKey.HexStringToByteArray(), PublicViewKey = request.PublicViewKey.HexStringToByteArray() }; issuanceDetails = await IssueIdpAttributesAsRoot(issuer, request.Protection, identity, issuanceInputDetails, account, targetAccount, statePersistency).ConfigureAwait(false); } else { issuanceDetails = await IssueIdpAttributesAsAssociated(issuer, identity, issuanceInputDetails, statePersistency).ConfigureAwait(false); } await _idenitiesHubContext.Clients.Group(account.AccountId.ToString()).SendAsync("RequestForIssuance", issuanceDetails); IIntegrationIdP integrationService = GetIntegrationService(account.AccountId); if (integrationService != null) { IssuanceDetails issuanceIntegration = new IssuanceDetails { RootAttribute = new IssuanceDetails.IssuanceDetailsRoot { AttributeName = issuanceDetails.RootAttribute.AttributeName, AssetCommitment = issuanceDetails.RootAttribute.AssetCommitment.HexStringToByteArray(), OriginatingCommitment = issuanceDetails.RootAttribute.OriginatingCommitment.HexStringToByteArray(), SurjectionProof = issuanceDetails.RootAttribute.SurjectionProof.HexStringToByteArray() }, AssociatedAttributes = issuanceDetails.AssociatedAttributes .Select(a => new IssuanceDetails.IssuanceDetailsAssociated { AttributeName = a.AttributeName, AssetCommitment = a.AssetCommitment.HexStringToByteArray(), BindingToRootCommitment = a.BindingToRootCommitment.HexStringToByteArray() }).ToList() }; integrationService.IssueAttributes(account.AccountId, issuanceIntegration); } var attributeValues = FillAttributeValues(request.Attributes, attributeDefinitions); return(Ok(attributeValues)); #region Internal Functions IReadOnlyCollection <AttributeValue> FillAttributeValues(Dictionary <string, IssueAttributesRequestDTO.AttributeValue> attributes, IEnumerable <AttributeDefinition> attributeDefinitions) { List <AttributeValue> attributeValues = new List <AttributeValue>(); var protectionAttrDefinition = attributeDefinitions.FirstOrDefault(a => a.SchemeName == AttributesSchemes.ATTR_SCHEME_NAME_PASSWORD); foreach (var attributeName in attributes.Keys.Where(a => protectionAttrDefinition?.AttributeName != a)) { string content = attributes[attributeName].Value; AttributeValue attributeValue = new AttributeValue { Value = content, Definition = attributeDefinitions.FirstOrDefault(d => d.AttributeName == attributeName) }; attributeValues.Add(attributeValue); } return(new ReadOnlyCollection <AttributeValue>(attributeValues)); } async Task <IssuanceDetailsDto> IssueIdpAttributesAsRoot( string issuer, IssuanceProtection protection, Identity identity, IEnumerable <AttributeIssuanceDetails> attributeIssuanceDetails, AccountDescriptor account, ConfidentialAccount targetAccount, StatePersistency statePersistency) { IssuanceDetailsDto issuanceDetails = new IssuanceDetailsDto(); IEnumerable <IdentitiesScheme> identitiesSchemes = _dataAccessService.GetAttributesSchemeByIssuer(issuer, true); var rootAttributeDetails = attributeIssuanceDetails.First(a => a.Definition.IsRoot); byte[] rootAssetId = await _assetsService.GenerateAssetId(rootAttributeDetails.Definition.SchemeName, rootAttributeDetails.Value.Value, issuer).ConfigureAwait(false); IdentityAttribute rootAttribute = identity.Attributes.FirstOrDefault(a => a.AttributeName == rootAttributeDetails.Definition.AttributeName); if (!CreateRootAttributeIfNeeded(statePersistency, rootAttribute, rootAssetId)) { var protectionAttribute = identity.Attributes.FirstOrDefault(a => a.AttributeName == AttributesSchemes.ATTR_SCHEME_NAME_PASSWORD); bool res = VerifyProtectionAttribute(protectionAttribute, protection.SignatureE.HexStringToByteArray(), protection.SignatureS.HexStringToByteArray(), protection.SessionCommitment.HexStringToByteArray()); if (!res) { _logger.Warning($"[{account.AccountId}]: Failed to verify Surjection Proofs of the Protection Attribute"); throw new ProtectionAttributeVerificationFailedException(); } } else { issuanceDetails.AssociatedAttributes = await IssueAssociatedAttributes( attributeIssuanceDetails.Where(a => !a.Definition.IsRoot) .ToDictionary(d => identity.Attributes.First(a => a.AttributeName == d.Definition.AttributeName).AttributeId, d => d), statePersistency.TransactionsService, issuer, rootAssetId).ConfigureAwait(false); } var packet = TransferAssetToUtxo(statePersistency.TransactionsService, targetAccount, rootAssetId); if (packet == null) { _logger.Error($"[{account.AccountId}]: failed to transfer Root Attribute"); throw new RootAttributeTransferFailedException(); } _dataAccessService.AddOrUpdateIdentityTarget(identity.IdentityId, targetAccount.PublicSpendKey.ToHexString(), targetAccount.PublicViewKey.ToHexString()); issuanceDetails.RootAttribute = new IssuanceDetailsDto.IssuanceDetailsRoot { AttributeName = rootAttribute.AttributeName, OriginatingCommitment = packet.SurjectionProof.AssetCommitments[0].ToHexString(), AssetCommitment = packet.TransferredAsset.AssetCommitment.ToHexString(), SurjectionProof = $"{packet.SurjectionProof.Rs.E.ToHexString()}{packet.SurjectionProof.Rs.S[0].ToHexString()}" }; return(issuanceDetails); } async Task <IssuanceDetailsDto> IssueIdpAttributesAsAssociated( string issuer, Identity identity, IEnumerable <AttributeIssuanceDetails> attributeIssuanceDetails, StatePersistency statePersistency) { IssuanceDetailsDto issuanceDetails = new IssuanceDetailsDto(); IdentitiesScheme rootScheme = _dataAccessService.GetRootIdentityScheme(issuer); IEnumerable <IdentitiesScheme> identitiesSchemes = _dataAccessService.GetAttributesSchemeByIssuer(issuer, true); var rootAttributeDetails = attributeIssuanceDetails.First(a => a.Definition.IsRoot); var packet = await IssueAssociatedAttribute( rootScheme.AttributeSchemeName, rootAttributeDetails.Value.Value, rootAttributeDetails.Value.BlindingPointValue, rootAttributeDetails.Value.BlindingPointRoot, issuer, statePersistency.TransactionsService).ConfigureAwait(false); _dataAccessService.UpdateIdentityAttributeCommitment(identity.Attributes.FirstOrDefault(a => a.AttributeName == rootScheme.AttributeName).AttributeId, packet.AssetCommitment); byte[] rootAssetId = _assetsService.GenerateAssetId(rootScheme.IdentitiesSchemeId, rootAttributeDetails.Value.Value); issuanceDetails.AssociatedAttributes = await IssueAssociatedAttributes( attributeIssuanceDetails .ToDictionary(d => identity.Attributes.First(a => a.AttributeName == d.Definition.AttributeName).AttributeId, d => d), statePersistency.TransactionsService, issuer, rootAssetId).ConfigureAwait(false); return(issuanceDetails); }