Skip to content

Feat/4086 anoncreds indy accum fix with endorsement#4090

Merged
jamshale merged 16 commits into
openwallet-foundation:mainfrom
jamshale:feat/4086-anoncreds-indy-accum-fix-with-endorsement
Mar 20, 2026
Merged

Feat/4086 anoncreds indy accum fix with endorsement#4090
jamshale merged 16 commits into
openwallet-foundation:mainfrom
jamshale:feat/4086-anoncreds-indy-accum-fix-with-endorsement

Conversation

@jamshale
Copy link
Copy Markdown
Contributor

Pull request overview

This PR refactors anoncreds revocation recovery by moving legacy Indy–specific recovery logic into the anoncreds/default/legacy_indy implementation, and adds an anoncreds-specific event path to trigger recovery when an endorsed revocation list update fails.

Changes:

  • Emit a new anoncreds event when endorsed revocation list updates fail, and add a legacy-indy event subscriber to trigger recovery/retry logic.
  • Move revocation recovery implementation code into anoncreds/default/legacy_indy/recover.py, leaving only shared exception(s) in anoncreds/revocation/recover.py.
  • Update tests and registry code to use the new recovery entry points.

@jamshale
Copy link
Copy Markdown
Contributor Author

I think this is getting pretty close. I originally thought I could do this easier but it ended up being quite a bit of refactoring.

I can add more unit tests for the retry logic and there's one other thing I want to go over.

@jamshale jamshale linked an issue Mar 16, 2026 that may be closed by this pull request
@jamshale jamshale force-pushed the feat/4086-anoncreds-indy-accum-fix-with-endorsement branch from 72e9d3b to 69b9a07 Compare March 17, 2026 19:52
@jamshale
Copy link
Copy Markdown
Contributor Author

I found another problem when testing self endorsement. The new event driven anoncreds revocation module was swallowing the exception from the update transaction. This prevents that from happening and then emits the same event as the failed endorsement transaction to get the flow working correctly.

I'd still like to add a bit more unit test coverage....

@jamshale jamshale requested review from PatStLouis and esune March 17, 2026 22:05
@jamshale
Copy link
Copy Markdown
Contributor Author

This could be reviewed now. I've been focusing mostly on manually testing this because you need to create a ledger error for it to occur.

I'll try and get a couple more unit tests in to boost it up.

@jamshale
Copy link
Copy Markdown
Contributor Author

I think this probably has enough unit testing now. Most of the missing code is exception paths and the main fix and retry function which would require a lot of mocking and the individual functions are unit tested.

@jamshale jamshale force-pushed the feat/4086-anoncreds-indy-accum-fix-with-endorsement branch from 104a750 to c288588 Compare March 18, 2026 19:17
rev_list.rev_reg_def_id,
txn_record_type=GET_REVOC_REG_ENTRY,
)
ledger = profile.inject_or(BaseLedger)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still don't really understand this yet but this solves the unknown did problem with multi-tenant and multi-ledger scenarios. Apparently you're only supposed to use IndyLedgerRequestsExecutor when reading from the ledger?

I'll keep looking for a bit if there's a reasonable way to fix this pattern. It's very easy to create bugs.

Copy link
Copy Markdown
Member

@esune esune left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes look good from the little I know about anoncreds/revocation. There's a couple test failures that need attention, other than that I think it's good.

jamshale added 14 commits March 19, 2026 00:40
…o legacy_indy plugin

Signed-off-by: jamshale <jamiehalebc@gmail.com>
Signed-off-by: jamshale <jamiehalebc@gmail.com>
Signed-off-by: jamshale <jamiehalebc@gmail.com>
Signed-off-by: jamshale <jamiehalebc@gmail.com>
Signed-off-by: jamshale <jamiehalebc@gmail.com>
Signed-off-by: jamshale <jamiehalebc@gmail.com>
Signed-off-by: jamshale <jamiehalebc@gmail.com>
Signed-off-by: jamshale <jamiehalebc@gmail.com>
Signed-off-by: jamshale <jamiehalebc@gmail.com>
Signed-off-by: jamshale <jamiehalebc@gmail.com>
Signed-off-by: jamshale <jamiehalebc@gmail.com>
Signed-off-by: jamshale <jamiehalebc@gmail.com>
Signed-off-by: jamshale <jamiehalebc@gmail.com>
Signed-off-by: jamshale <jamiehalebc@gmail.com>
@jamshale jamshale force-pushed the feat/4086-anoncreds-indy-accum-fix-with-endorsement branch from 9cf8338 to ac9fa9e Compare March 19, 2026 00:40
@jamshale
Copy link
Copy Markdown
Contributor Author

Tests fixed now. The last small change needed updated mocking.

Copy link
Copy Markdown
Contributor

@PatStLouis PatStLouis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this looks good. I won't put this as a blocker, but I think there could probably be some more comments in the code and these functions to capture the flow and how things work together for future maintainers while its fresh in memory. This is a complex sequence of operations.

async def generate_ledger_rrrecovery_txn(genesis_txns: str, rev_list: RevList) -> dict:
"""Generate a new ledger accum entry, using the wallet value if revocations ahead of ledger.""" # noqa: E501
registry_from_ledger, prev_revoked = await fetch_txns(
async def generate_ledger_rrrecovery_txn(genesis_txns: str, rev_list: RevList):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we fix this function name spelling?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought this was a deliberate name for something like revocation registry recovery transaction, but if it is not I agree we should fix it

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was just copied straight from the existing implementation. But, yes I might as well change it with the rest of the refactor.

registry_from_ledger, prev_revoked = await fetch_txns(
async def generate_ledger_rrrecovery_txn(genesis_txns: str, rev_list: RevList):
"""Generate a new ledger accum entry, based on wallet vs ledger revocation state."""
new_delta = None
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this variable seems pointless? its only being set to none and returned as none?

return endorser_did, connection_record


async def _track_retry(cache: BaseCache, accum: str):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused by this function, is the accum the retry value? what's the logic behind this?

@jamshale
Copy link
Copy Markdown
Contributor Author

I think this looks good. I won't put this as a blocker, but I think there could probably be some more comments in the code and these functions to capture the flow and how things work together for future maintainers while its fresh in memory. This is a complex sequence of operations.

I'll do a round of commenting... I agree it's a complicated sequence of events and there's 2 separate flows for self endorsement and using an endorser which makes it quite confusing.

@esune
Copy link
Copy Markdown
Member

esune commented Mar 19, 2026

I think this looks good. I won't put this as a blocker, but I think there could probably be some more comments in the code and these functions to capture the flow and how things work together for future maintainers while its fresh in memory. This is a complex sequence of operations.

I'll do a round of commenting... I agree it's a complicated sequence of events and there's 2 separate flows for self endorsement and using an endorser which makes it quite confusing.

For the future: I know endorsement is pretty much baked into some of the core functionality, as a longer-term strategy we could consider refactoring it and extracting it to a plugin - using an event-driven pattern.

@jamshale
Copy link
Copy Markdown
Contributor Author

For the future: I know endorsement is pretty much baked into some of the core functionality, as a longer-term strategy we could consider refactoring it and extracting it to a plugin - using an event-driven pattern.

I think the endorsement protocol and module is so indy specific it should be taken out as a wider legacy_indy plugin. This would include all of the indy and ledger code and the anoncreds plugin. This would be a large plugin but would make using legacy indy way simpler and would make acapy core way simpler. I was working on this for a while after Christmas and there's some challenges but I think it's doable. I don't see a big benefit in just moving the endorsement protocol itself into a plugin.

Signed-off-by: jamshale <jamiehalebc@gmail.com>
Signed-off-by: jamshale <jamiehalebc@gmail.com>
@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
75.9% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

@jamshale jamshale merged commit 5c18edc into openwallet-foundation:main Mar 20, 2026
11 of 12 checks passed
jamshale added a commit to jamshale/acapy that referenced this pull request Mar 23, 2026
…ation#4090)

* feat: Trigger revocation recovery with endorsement / Move indy code to legacy_indy plugin

Signed-off-by: jamshale <jamiehalebc@gmail.com>

* fix: Co-pilot suggestions

Signed-off-by: jamshale <jamiehalebc@gmail.com>

* fix: Better session management and more null object handling

Signed-off-by: jamshale <jamiehalebc@gmail.com>

* chore: Remove indy specific usage from anoncreds manager

Signed-off-by: jamshale <jamiehalebc@gmail.com>

* Some fixes and hardening

Signed-off-by: jamshale <jamiehalebc@gmail.com>

* Remove comment

Signed-off-by: jamshale <jamiehalebc@gmail.com>

* Refactor / Add self endorsment support / Unit tests

Signed-off-by: jamshale <jamiehalebc@gmail.com>

* fix: Use old ruff version to format

Signed-off-by: jamshale <jamiehalebc@gmail.com>

* Small fixes

Signed-off-by: jamshale <jamiehalebc@gmail.com>

* Add a bit more unit test coverage

Signed-off-by: jamshale <jamiehalebc@gmail.com>

* bit more test coverage

Signed-off-by: jamshale <jamiehalebc@gmail.com>

* Add another test

Signed-off-by: jamshale <jamiehalebc@gmail.com>

* fix: Don't use IndyLedgerRequestsExecutor when posting to ledger

Signed-off-by: jamshale <jamiehalebc@gmail.com>

* Fix unit tests

Signed-off-by: jamshale <jamiehalebc@gmail.com>

* Refactor and additional commenting

Signed-off-by: jamshale <jamiehalebc@gmail.com>

* Fix mocks

Signed-off-by: jamshale <jamiehalebc@gmail.com>

---------

Signed-off-by: jamshale <jamiehalebc@gmail.com>
revocation_list=[1, 0, 0, 0],
),
recovery_txn={"value": "txn"},
endorser_did=None,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jamshale -- I'm comparing the LTS PR to this PR and saw these warnings in here from SonarCloud about type issues. I'm assuming you saw them, but just wanted to be sure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Anoncreds Indy - Accumulator fix with endorsement

4 participants