Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include dedup info in get stamp #743

Merged
merged 43 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
dfa59cd
wip: testing v2 api
nutrina Dec 3, 2024
b7585fd
fix: handle failing tests and wrong value returned in in V2 api
Dec 4, 2024
448759f
fix: failing tests
Dec 4, 2024
0523c14
Include dedup info in get stamp
larisa17 Nov 29, 2024
95b2d73
update submit passport v2 test
larisa17 Nov 29, 2024
c026cef
update registry schema
larisa17 Nov 29, 2024
e57e6ca
remove submit passport call from v2
larisa17 Nov 29, 2024
11e0a59
set default for clashing stamps
larisa17 Nov 29, 2024
0a66afd
adjust test dedup
larisa17 Nov 29, 2024
970147a
fix data dump test
larisa17 Nov 29, 2024
90a4966
update lambda call
larisa17 Nov 29, 2024
ee34d94
minor updates
larisa17 Dec 3, 2024
d45d996
update return message
larisa17 Dec 3, 2024
ac2b4b0
add single function
larisa17 Dec 4, 2024
5686e6f
update v2 tests
larisa17 Dec 4, 2024
9998fbb
update handle_scoring
larisa17 Dec 4, 2024
2bd28ea
update response
larisa17 Dec 4, 2024
5f6f415
update return data type
larisa17 Dec 4, 2024
ffa3309
update tests
larisa17 Dec 4, 2024
bac5989
update tests passport
larisa17 Dec 4, 2024
979f5ea
update passport tests
larisa17 Dec 4, 2024
abbcaf6
add api dedup test
larisa17 Dec 9, 2024
153a2f9
minor updates
larisa17 Dec 9, 2024
160b510
fix returned expiration date
larisa17 Dec 9, 2024
885dead
add new flow for deduplication
larisa17 Dec 9, 2024
0d86775
update schema
larisa17 Dec 9, 2024
8c2896f
update tests
larisa17 Dec 9, 2024
fb0e653
pass expiration dates
larisa17 Dec 9, 2024
8045766
update test stamp get score
larisa17 Dec 9, 2024
9ffc6f6
update v2/aws_lambdas/tests/test_stamp_score_get.py
larisa17 Dec 9, 2024
fa43e5c
update tests
larisa17 Dec 9, 2024
c0e07b7
update test_passport_submission.py
larisa17 Dec 9, 2024
4d63f3a
update tests
larisa17 Dec 9, 2024
0dc33ed
adjust score tests
larisa17 Dec 9, 2024
12c46df
rename stamp expiration dates
larisa17 Dec 10, 2024
917a5d7
modify clashing stamps
larisa17 Dec 10, 2024
4a0e7e1
update schema
larisa17 Dec 10, 2024
71a1ab6
add clashing stamps in ret
larisa17 Dec 10, 2024
7c78eb9
update lambda test and score format
larisa17 Dec 10, 2024
46e390a
update test for dedup
larisa17 Dec 10, 2024
148a863
update lifo tests
larisa17 Dec 10, 2024
ff8e363
update test for return score format
larisa17 Dec 10, 2024
f0d9c1f
update resposne schema & tests
larisa17 Dec 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions api/account/deduplication/lifo.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import copy
from typing import Tuple

import api_logging as logging
from account.models import Community
from django.conf import settings
from django.db import IntegrityError

import api_logging as logging
from account.models import Community
from registry.models import Event, HashScorerLink, Stamp
from registry.utils import get_utc_time

Expand Down Expand Up @@ -128,8 +129,7 @@ async def arun_lifo_dedup(
for stamp in clashing_stamps
]
)

return (deduped_passport, None)
return (deduped_passport, None, clashing_stamps)


async def save_hash_links(
Expand Down
15 changes: 8 additions & 7 deletions api/account/test/test_deduplication_lifo.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
from unittest import mock

from account.deduplication import Rules
from account.deduplication.lifo import HashScorerLinkIntegrityError, alifo
from account.models import Account, Community
from asgiref.sync import async_to_sync
from django.conf import settings
from django.contrib.auth import get_user_model
from django.test import TransactionTestCase
from ninja_jwt.schema import RefreshToken

from account.deduplication import Rules
from account.deduplication.lifo import HashScorerLinkIntegrityError, alifo
from account.models import Account, Community
from registry.models import HashScorerLink, Passport, Stamp
from scorer_weighted.models import Scorer, WeightedScorer

Expand Down Expand Up @@ -83,7 +84,7 @@ async def test_lifo_no_deduplicate_across_cummunities(self):
credential=credential,
)

deduped_passport, _ = await alifo(
deduped_passport, _, _ = await alifo(
passport1.community, {"stamps": [credential]}, passport1.address
)

Expand Down Expand Up @@ -121,7 +122,7 @@ async def test_lifo_no_deduplicate_same_passport_address_across_cummunities(self
credential=credential,
)

deduped_passport, _ = await alifo(
deduped_passport, _, _ = await alifo(
passport1.community, {"stamps": [credential]}, passport1.address
)

Expand All @@ -140,7 +141,7 @@ async def test_lifo_deduplicate(self):
)

# We test deduplication of the 1st passport (for example user submits the same passport again)
deduped_passport, _ = await alifo(
deduped_passport, _, _ = await alifo(
passport.community, {"stamps": [credential]}, passport.address
)

Expand All @@ -157,7 +158,7 @@ async def test_lifo_deduplicate(self):

# We test deduplication of another passport with different address but
# with the same stamp
deduped_passport, _ = await alifo(
deduped_passport, _, _ = await alifo(
passport.community, {"stamps": [credential]}, "0xaddress_2"
)

Expand Down
1 change: 1 addition & 0 deletions api/ceramic_cache/test/test_cmd_scorer_dump_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ def upload_file(self, file_name, *args, **kwargs):
"error",
"evidence",
"stamp_scores",
"stamps",
"id",
}
expected_passport_keys = {"address", "community", "requires_calculation"}
Expand Down
41 changes: 36 additions & 5 deletions api/registry/atasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,12 @@ async def aload_passport_data(address: str) -> Dict:
return passport_data


async def acalculate_score(passport: Passport, community_id: int, score: Score):
async def acalculate_score(
passport: Passport,
community_id: int,
score: Score,
clashing_stamps: list[dict] = [],
):
log.debug("Scoring")
user_community = await Community.objects.aget(pk=community_id)

Expand All @@ -104,6 +109,32 @@ async def acalculate_score(passport: Passport, community_id: int, score: Score):
score.error = None
score.stamp_scores = scoreData.stamp_scores
score.expiration_date = scoreData.expiration_date
stamps = {}
for stamp_name, stamp_score in scoreData.stamp_scores.items():
# Find if the stamp_name matches any provider in clashing_stamps
matching_stamp = next(
(stamp for stamp in clashing_stamps if stamp_name == stamp["provider"]),
None,
)

# Construct the stamps dictionary
stamps[stamp_name] = {
"score": str(stamp_score),
"dedup": matching_stamp is not None,
"expiration_date": matching_stamp["credential"]["expirationDate"]
if matching_stamp
else scoreData.expiration_dates[stamp_name].isoformat(),
}
# Add stamps present in clashing_stamps but not in stamp_scores
for c_stamp in clashing_stamps:
provider_name = c_stamp["provider"]
if provider_name not in stamps:
stamps[provider_name] = {
"score": "0", # Default score for stamps not in stamp_scores
"dedup": True,
"expiration_date": c_stamp["credential"]["expirationDate"],
}
score.stamps = stamps
log.info("Calculated score: %s", score)


Expand All @@ -126,7 +157,7 @@ async def aprocess_deduplication(passport, community, passport_data, score: Scor
if not method:
raise Exception("Invalid rule")

deduplicated_passport, affected_passports = await method(
deduplicated_passport, affected_passports, clashing_stamps = await method(
community, passport_data, passport.address
)

Expand All @@ -151,7 +182,7 @@ async def aprocess_deduplication(passport, community, passport_data, score: Scor
# await acalculate_score(passport, passport.community_id, affected_score)
# await affected_score.asave()

return deduplicated_passport
return (deduplicated_passport, clashing_stamps)


async def avalidate_credentials(passport: Passport, passport_data) -> dict:
Expand Down Expand Up @@ -223,12 +254,12 @@ async def ascore_passport(
try:
passport_data = await aload_passport_data(address)
validated_passport_data = await avalidate_credentials(passport, passport_data)
deduped_passport_data = await aprocess_deduplication(
(deduped_passport_data, clashing_stamps) = await aprocess_deduplication(
passport, community, validated_passport_data, score
)
await asave_stamps(passport, deduped_passport_data)
await aremove_stale_stamps_from_db(passport, deduped_passport_data)
await acalculate_score(passport, community.pk, score)
await acalculate_score(passport, community.pk, score, clashing_stamps)

except APIException as e:
log.error(
Expand Down
17 changes: 17 additions & 0 deletions api/registry/migrations/0042_score_stamps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 4.2.6 on 2024-11-28 20:07

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("registry", "0041_weightconfiguration_description"),
]

operations = [
migrations.AddField(
model_name="score",
name="stamps",
field=models.JSONField(blank=True, null=True),
),
]
1 change: 1 addition & 0 deletions api/registry/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ class Status:
error = models.TextField(null=True, blank=True)
evidence = models.JSONField(null=True, blank=True)
stamp_scores = models.JSONField(null=True, blank=True)
stamps = models.JSONField(null=True, blank=True)

expiration_date = models.DateTimeField(
default=None, null=True, blank=True, db_index=True
Expand Down
2 changes: 1 addition & 1 deletion api/registry/test/test_passport_get_score.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import datetime
from urllib.parse import urlencode

import pytest
from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
from django.test import Client
from web3 import Web3
from urllib.parse import urlencode

from account.models import Account, AccountAPIKey, Community
from registry.api.v1 import get_scorer_by_id
Expand Down
1 change: 1 addition & 0 deletions api/scorer/config/gitcoin_passport_weights.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"IdenaState#Verified": "2.029",
"Lens": "0.93",
"Linkedin": "1.531",
"LinkedinV2": "1.531",
"NFT": "1.032",
"NFTScore#50": "10.033",
"NFTScore#75": "2.034",
Expand Down
2 changes: 2 additions & 0 deletions api/scorer/test/test_choose_binary_scorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ def _(scorer_community_with_binary_scorer, scorer_api_key):
"sum_of_weights": Decimal("70"),
"earned_points": {},
"expiration_date": datetime.now(timezone.utc),
"expiration_dates": {},
}
],
):
Expand Down Expand Up @@ -220,6 +221,7 @@ def _(scorer_community_with_binary_scorer, scorer_api_key):
"sum_of_weights": Decimal("90"),
"earned_points": {},
"expiration_date": datetime.now(timezone.utc),
"expiration_dates": {},
}
],
):
Expand Down
14 changes: 12 additions & 2 deletions api/scorer_weighted/computation.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from datetime import datetime
from decimal import Decimal
from math import e
from typing import Dict, List

import api_logging as logging
from account.models import Customization
from registry.models import Stamp
from scorer_weighted.models import WeightedScorer
from account.models import Customization
from datetime import datetime

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -46,6 +47,7 @@ def calculate_weighted_score(
scored_providers = []
earned_points = {}
earliest_expiration_date = None
expiration_dates = {}
for stamp in Stamp.objects.filter(passport_id=passport_id):
if stamp.provider not in scored_providers:
weight = Decimal(weights.get(stamp.provider, 0))
Expand All @@ -55,6 +57,7 @@ def calculate_weighted_score(
expiration_date = datetime.fromisoformat(
stamp.credential["expirationDate"]
)
expiration_dates[stamp.provider] = expiration_date
# Compute the earliest expiration date for the stamps used to calculate the score
# as this will be the expiration date of the score
if (
Expand All @@ -69,6 +72,7 @@ def calculate_weighted_score(
"sum_of_weights": sum_of_weights,
"earned_points": earned_points,
"expiration_date": earliest_expiration_date,
"expiration_dates": expiration_dates,
}
)
return ret
Expand All @@ -95,6 +99,7 @@ def recalculate_weighted_score(
scored_providers = []
earned_points = {}
earliest_expiration_date = None
expiration_dates = {}
for stamp in stamp_list:
if stamp.provider not in scored_providers:
weight = Decimal(weights.get(stamp.provider, 0))
Expand All @@ -104,6 +109,7 @@ def recalculate_weighted_score(
expiration_date = datetime.fromisoformat(
stamp.credential["expirationDate"]
)
expiration_dates[stamp.provider] = expiration_date
# Compute the earliest expiration date for the stamps used to calculate the score
# as this will be the expiration date of the score
if (
Expand All @@ -118,6 +124,7 @@ def recalculate_weighted_score(
"sum_of_weights": sum_of_weights,
"earned_points": earned_points,
"expiration_date": earliest_expiration_date,
"expiration_dates": expiration_dates,
}
)
return ret
Expand Down Expand Up @@ -158,6 +165,7 @@ async def acalculate_weighted_score(
sum_of_weights: Decimal = Decimal(0)
scored_providers = []
earned_points = {}
expiration_dates = {}
earliest_expiration_date = None
async for stamp in Stamp.objects.filter(passport_id=passport_id):
if stamp.provider not in scored_providers:
Expand All @@ -168,6 +176,7 @@ async def acalculate_weighted_score(
expiration_date = datetime.fromisoformat(
stamp.credential["expirationDate"]
)
expiration_dates[stamp.provider] = expiration_date
# Compute the earliest expiration date for the stamps used to calculate the score
# as this will be the expiration date of the score
if (
Expand All @@ -183,6 +192,7 @@ async def acalculate_weighted_score(
"sum_of_weights": sum_of_weights,
"earned_points": earned_points,
"expiration_date": earliest_expiration_date,
"expiration_dates": expiration_dates,
}
)
return ret
7 changes: 7 additions & 0 deletions api/scorer_weighted/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,13 @@ def __init__(
evidence: Optional[List[ThresholdScoreEvidence]],
points: dict,
expiration_date: datetime,
expiration_dates: dict,
):
self.score = score
self.evidence = evidence
self.stamp_scores = points
self.expiration_date = expiration_date
self.expiration_dates = expiration_dates

def __repr__(self):
return f"ScoreData(score={self.score}, evidence={self.evidence})"
Expand Down Expand Up @@ -125,6 +127,7 @@ def recompute_score(
evidence=None,
points=s["earned_points"],
expiration_date=s["expiration_date"],
expiration_dates=s["expiration_dates"],
)
for s in recalculate_weighted_score(
self, passport_ids, stamps, community_id
Expand All @@ -145,6 +148,7 @@ async def acompute_score(self, passport_ids, community_id: int) -> List[ScoreDat
evidence=None,
points=s["earned_points"],
expiration_date=s["expiration_date"],
expiration_dates=s["expiration_dates"],
)
for s in scores
]
Expand Down Expand Up @@ -187,6 +191,7 @@ def compute_score(self, passport_ids, community_id: int) -> List[ScoreData]:
],
points=rawScore["earned_points"],
expiration_date=rawScore["expiration_date"],
expiration_dates=rawScore["expiration_dates"],
),
rawScores,
binaryScores,
Expand Down Expand Up @@ -221,6 +226,7 @@ def recompute_score(
],
points=rawScore["earned_points"],
expiration_date=rawScore["expiration_date"],
expiration_dates=rawScore["expiration_dates"],
),
rawScores,
binaryScores,
Expand Down Expand Up @@ -253,6 +259,7 @@ async def acompute_score(self, passport_ids, community_id: int) -> List[ScoreDat
],
points=rawScore["earned_points"],
expiration_date=rawScore["expiration_date"],
expiration_dates=rawScore["expiration_dates"],
),
rawScores,
binaryScores,
Expand Down
Loading
Loading