Python wrapper verification error when there are multiple revocation registry entries
conanoc opened this issue · 2 comments
This is the reason for the error openwallet-foundation/acapy#2036
The problem is here:
https://github.com/hyperledger/indy-shared-rs/blob/v0.3.1/wrappers/python/indy_credx/types.py#L457-L464
The RevocationRegistry
created at L459 will be deallocated outside the for loop, but it's handle entry.handle
at L462 should be retained by the reg_entries
list.
This would work if the RevocationEntry
at L461 is not Structure
type. RevocationEntry
subclasses Structure
of ctypes and this makes entry.handle
deallocated before bindings.verify_presentation()
starts.
I could make it work by retaining the RevocationRegistry
created at L459 in a dummy list to prevent deallocation, which also prevents the deallocation of its handle.
You may wonder why it works when there is only one revocation entry. I suppose it's dependent on the GC behavior of python.
I created a sample code to see this issue.
from ctypes import c_int64, Structure, c_char_p
class Age(c_int64):
def __del__(self):
print(f"Age: delete called for {self.value}")
class Applicant:
def __init__(self, name, age = None):
self.name = name
if not age:
age = Age(0)
self.age = age
def __del__(self):
print(f"Applicant: delete called for {self.name}")
class Candidate(Structure):
_fields_ = [("name", c_char_p), ("age", Age)]
@classmethod
def create(
cls,
name,
age,
):
return Candidate(name=c_char_p(name.encode("utf-8")), age=age)
def print_candidates(applicants):
candidates = []
for applicant in applicants:
if not isinstance(applicant, Applicant):
applicant = Applicant(applicant)
print("== appending candidate: ", applicant.name)
candidates.append(Candidate.create(applicant.name, applicant.age)) # <-- applicant.age is not retained by this because Candidate is a Struct.
print("== print candidates ==")
for candidate in candidates:
print(candidate.name)
print("== print multiple candidates ==")
applicants = [
"Alice",
Applicant("Bob", Age(30)),
]
print_candidates(applicants)
print("== print a single candidate ==")
applicants = [
"Alice",
]
print_candidates(applicants)
You can find that the Age
instance, which corresponds to ObjectHandle
, is deallocated before printing the candidates when there is more than one entry.
This is the output of the sample code above:
== print multiple candidates ==
== appending candidate: Alice
Applicant: delete called for Alice
Age: delete called for 0
== appending candidate: Bob
== print candidate ==
b'Alice'
b'Bob'
== print a single candidate ==
Applicant: delete called for Bob
Age: delete called for 30
== appending candidate: Alice
== print candidate ==
b'Alice'
Applicant: delete called for Alice
Age: delete called for 0
Heads up on this issue @andrewwhitehead @TimoGlastra @blu3beri and @whalelephant. This will need to be looked at in the anoncreds-rs for sure, perhaps retrofitted here as well.
Thanks for diving into this @conanoc .