Skip to content

Commit

Permalink
fix: update smids and rmids for group lead on new event
Browse files Browse the repository at this point in the history
The prior code would fix smids and rmids for all new rotation members on each rotation yet would not fix the smids and rmids for the group lead submitting the multisig event because of the early return when the serder arg is not present. This fixes that

Signed-off-by: Kent Bull <[email protected]>
  • Loading branch information
kentbull committed Sep 5, 2024
1 parent 9d9a481 commit f4ed386
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 9 deletions.
22 changes: 13 additions & 9 deletions src/keri/app/habbing.py
Original file line number Diff line number Diff line change
Expand Up @@ -2745,13 +2745,21 @@ def make(self, *, code=coring.MtrDex.Blake3_256, transferable=True, isith=None,

self.inited = True

def _update_smids_rmids(self, smids, rmids):
if (habord := self.db.habs.get(keys=(self.pre,))) is None:
raise kering.ValidationError(f"Missing HabitatRecord for pre={self.pre}")
self.smids = smids
self.rmids = rmids
habord.smids = smids
habord.rmids = rmids
self.db.habs.pin(keys=self.pre, val=habord)

def rotate(self, smids=None, rmids=None, serder=None, **kwargs):

if serder is None:
return super(GroupHab, self).rotate(**kwargs)

if (habord := self.db.habs.get(keys=(self.pre,))) is None:
raise kering.ValidationError(f"Missing HabitatRecord for pre={self.pre}")
msg = super(GroupHab, self).rotate(**kwargs)
self._update_smids_rmids(smids, rmids)
return msg

# sign handles group hab with .mhab case
sigers = self.sign(ser=serder.raw, verfers=serder.verfers, rotated=True)
Expand All @@ -2767,11 +2775,7 @@ def rotate(self, smids=None, rmids=None, serder=None, **kwargs):
raise kering.ValidationError("Improper Habitat rotation for "
"pre={self.pre}.") from ex

self.smids = smids
self.rmids = rmids
habord.smids = smids
habord.rmids = rmids
self.db.habs.pin(keys=(self.pre,), val=habord)
self._update_smids_rmids(smids, rmids)

return msg

Expand Down
94 changes: 94 additions & 0 deletions tests/app/test_grouping.py
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,100 @@ def test_multisig_rotate(mockHelpingNowUTC):
assert data["gid"] == ghab1.pre
assert "rot" in exn.ked["e"]

def test_multisig_rotate_new_group_member_updates_smids(mockHelpingNowUTC):
# Create a multisig with three members, test_1, test_2, and test_3
with openMultiSig(prefix="smidstest") as ((hby1, ghab1), (hby2, ghab2), (hby3, ghab3)):
# Create a new member, test_4
with habbing.openHab(name="smidstest_4", salt=b'0123456789abcdef', transferable=True, temp=True) as (hby4, hab4):
icp4 = hab4.makeOwnEvent(sn=0) # Get test_4's inception event to introduce to group members

hab1 = hby1.habByName("smidstest_1")
hab2 = hby2.habByName("smidstest_2")
hab3 = hby3.habByName("smidstest_3")
# Create member Kevery instances to parse each other's events and update their keystate
kev1 = eventing.Kevery(db=hab1.db, lax=True, local=False)
kev2 = eventing.Kevery(db=hab2.db, lax=True, local=False)
kev3 = eventing.Kevery(db=hab3.db, lax=True, local=False)
kev4 = eventing.Kevery(db=hab4.db, lax=True, local=False)

# Introduce test_4 member to group by parsing test_4's inception event (latest key state)
parsing.Parser().parse(ims=bytearray(icp4), kvy=kev1)
parsing.Parser().parse(ims=bytearray(icp4), kvy=kev2)
parsing.Parser().parse(ims=bytearray(icp4), kvy=kev3)
# introduce each member to 4
parsing.Parser().parse(ims=bytearray(hab1.makeOwnEvent(sn=0)), kvy=kev4)
parsing.Parser().parse(ims=bytearray(hab2.makeOwnEvent(sn=0)), kvy=kev4)
parsing.Parser().parse(ims=bytearray(hab3.makeOwnEvent(sn=0)), kvy=kev4)

# rotate each individual hab to satisfy the rotation threshold with new keys
hab1.rotate()
hab2.rotate()
hab3.rotate()

# Update keystate in each hab for each other member
rot1 = hab1.makeOwnEvent(sn=1) # get latest event for hab1 and update keystate for other members
parsing.Parser().parse(ims=bytearray(rot1), kvy=kev2)
parsing.Parser().parse(ims=bytearray(rot1), kvy=kev3)
parsing.Parser().parse(ims=bytearray(rot1), kvy=kev4)

rot2 = hab2.makeOwnEvent(sn=1) # get latest event for hab2 and update keystate for other members
parsing.Parser().parse(ims=bytearray(rot2), kvy=kev1)
parsing.Parser().parse(ims=bytearray(rot2), kvy=kev3)
parsing.Parser().parse(ims=bytearray(rot2), kvy=kev4)

rot3 = hab3.makeOwnEvent(sn=1) # get latest event for hab3 and update keystate for other members
parsing.Parser().parse(ims=bytearray(rot3), kvy=kev1)
parsing.Parser().parse(ims=bytearray(rot3), kvy=kev2)
parsing.Parser().parse(ims=bytearray(rot3), kvy=kev4)

# create signing and rotation member AID lists for upcoming rotation
smids = [hab1.pre, hab2.pre, hab3.pre, hab4.pre]
rmids = [hab1.pre, hab2.pre, hab3.pre, hab4.pre]

# make group hab for test_4
ghab4 = hby4.joinGroupHab(hab4.pre, group="smidstest_group4", mhab=hab4, smids=smids, rmids=rmids)

isith = '["1/4", "1/4", "1/4", "1/4"]'
nsith = '["1/4", "1/4", "1/4", "1/4"]'
merfers = [hab1.kever.verfers[0], hab2.kever.verfers[0], hab3.kever.verfers[0], hab4.kever.verfers[0]]
migers = [hab1.kever.ndigers[0], hab2.kever.ndigers[0], hab3.kever.ndigers[0], hab4.kever.ndigers[0]]
rot = ghab1.rotate(smids=smids, rmids=rmids, isith=isith, nsith=nsith, toad=None, cuts=None, adds=None, data=None,
verfers=merfers, digers=migers)
rserder = serdering.SerderKERI(raw=rot)

# start counselor for group hab 1
prefixer = coring.Prefixer(qb64=ghab1.pre)
seqner = coring.Seqner(sn=ghab1.kever.sn + 1)
saider = coring.Saider(qb64=rserder.said)
counselor = grouping.Counselor(hby=hby1)
counselor.start(ghab=ghab1, prefixer=prefixer, seqner=seqner, saider=saider)

# hab2 signs rotation event and parse into hab1 Kevery
sigers2 = hab2.mgr.sign(rserder.raw, verfers=hab2.kever.verfers, indexed=True, indices=[1])
msg2 = eventing.messagize(serder=rserder, sigers=sigers2)
parsing.Parser().parse(ims=bytearray(msg2), kvy=kev1)

# hab3 signs rotation event and parse into hab1 Kevery
sigers3 = hab3.mgr.sign(rserder.raw, verfers=hab3.kever.verfers, indexed=True, indices=[2])
msg3 = eventing.messagize(serder=rserder, sigers=sigers3)
parsing.Parser().parse(ims=bytearray(msg3), kvy=kev1)

# hab4 signs rotation event and parse into hab1 Kevery. This should commit the event
sigers4 = hab4.mgr.sign(rserder.raw, verfers=hab4.kever.verfers, indexed=True, indices=[3])
msg4 = eventing.messagize(serder=rserder, sigers=sigers4)
parsing.Parser().parse(ims=bytearray(msg4), kvy=kev1)

kev1.processEscrows() # Runs escrows for Kevery1 so he processes all sigs together

counselor.processEscrows() # Get the rest of the way through counselor.
assert counselor.complete(prefixer=prefixer, seqner=seqner, saider=saider)
assert ghab4.smids == smids
assert ghab4.rmids == rmids
hby1.loadHabs()
ghab1 = hby1.habByName("smidstest_group1") # reload hab to get updated smids and rmids values
assert ghab1.smids == smids
assert ghab1.rmids == rmids


def test_multisig_interact(mockHelpingNowUTC):
with openMultiSig(prefix="test") as ((hby1, ghab1), (_, _), (_, _)):
Expand Down

0 comments on commit f4ed386

Please sign in to comment.