Skip to content

Commit

Permalink
Gnosis Integration + UAL extension + UAL validation + JWT Auth (#20)
Browse files Browse the repository at this point in the history
- Added Gnosis Chiado support
- Added possibility to get Gas Price through the Oracle API
- [Disabled] Added mechanism for automatic contract instance update when
contract is updated in the Hub
- Added support for the new UAL format
- Added function for advanced UAL validation
- Added JWT token based authentication for the DKG node connection
- Updated ABI files
- Improved error handling for DKG Node requests
  • Loading branch information
u-hubar authored Dec 21, 2023
2 parents b128ae1 + cacf7a0 commit 25092f5
Show file tree
Hide file tree
Showing 31 changed files with 869 additions and 246 deletions.
130 changes: 93 additions & 37 deletions dkg/asset.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,10 @@

from pyld import jsonld
from web3 import Web3
from web3.constants import HASH_ZERO
from web3.constants import ADDRESS_ZERO, HASH_ZERO
from web3.exceptions import ContractLogicError

from dkg.constants import (BLOCKCHAINS, DEFAULT_HASH_FUNCTION_ID,
DEFAULT_SCORE_FUNCTION_ID,
from dkg.constants import (DEFAULT_HASH_FUNCTION_ID, DEFAULT_SCORE_FUNCTION_ID,
PRIVATE_ASSERTION_PREDICATE,
PRIVATE_CURRENT_REPOSITORY,
PRIVATE_HISTORICAL_REPOSITORY)
Expand Down Expand Up @@ -54,6 +53,71 @@ class ContentAsset(Module):
def __init__(self, manager: DefaultRequestManager):
self.manager = manager

_owner = Method(BlockchainRequest.owner_of)

def is_valid_ual(self, ual: UAL) -> bool:
if not ual or not isinstance(ual, str):
raise ValueError("UAL must be a non-empty string.")

parts = ual.split("/")
if len(parts) != 3:
raise ValueError("UAL format is incorrect.")

prefixes = parts[0].split(":")
prefixes_number = len(prefixes)
if prefixes_number != 3 and prefixes_number != 4:
raise ValueError("Prefix format in UAL is incorrect.")

if prefixes[0] != "did":
raise ValueError(
f"Invalid DID prefix. Expected: 'did'. Received: '{prefixes[0]}'."
)

if prefixes[1] != "dkg":
raise ValueError(
f"Invalid DKG prefix. Expected: 'dkg'. Received: '{prefixes[1]}'."
)

if prefixes[2] != (
blockchain_name := (
self.manager.blockchain_provider.blockchain_id.split(":")[0]
)
):
raise ValueError(
"Invalid blockchain name in the UAL prefix. "
f"Expected: '{blockchain_name}'. Received: '${prefixes[2]}'."
)

if prefixes_number == 4:
chain_id = self.manager.blockchain_provider.blockchain_id.split(":")[1]

if int(prefixes[3]) != int(chain_id):
raise ValueError(
"Chain ID in UAL does not match the blockchain. "
f"Expected: '${chain_id}'. Received: '${prefixes[3]}'."
)

contract_address = self.manager.blockchain_provider.contracts[
"ContentAssetStorage"
].address

if parts[1].lower() != contract_address.lower():
raise ValueError(
"Contract address in UAL does not match. "
f"Expected: '${contract_address.lower()}'. "
f"Received: '${parts[1].lower()}'."
)

try:
owner = self._owner(int(parts[2]))

if not owner or owner == ADDRESS_ZERO:
raise ValueError("Token does not exist or has no owner.")

return True
except Exception as err:
raise ValueError(f"Error fetching asset owner: {err}")

_get_contract_address = Method(BlockchainRequest.get_contract_address)
_get_current_allowance = Method(BlockchainRequest.allowance)

Expand All @@ -70,9 +134,7 @@ def get_current_allowance(self, spender: Address | None = None) -> Wei:
_increase_allowance = Method(BlockchainRequest.increase_allowance)
_decrease_allowance = Method(BlockchainRequest.decrease_allowance)

def set_allowance(
self, token_amount: Wei, spender: Address | None = None
) -> Wei:
def set_allowance(self, token_amount: Wei, spender: Address | None = None) -> Wei:
if spender is None:
spender = self._get_contract_address("ServiceAgreementV1")

Expand Down Expand Up @@ -127,6 +189,7 @@ def create(
immutable: bool = False,
content_type: Literal["JSON-LD", "N-Quads"] = "JSON-LD",
) -> dict[str, HexStr | dict[str, str]]:
blockchain_id = self.manager.blockchain_provider.blockchain_id
assertions = format_content(content, content_type)

public_assertion_id = MerkleTree(
Expand All @@ -135,15 +198,14 @@ def create(
).root
public_assertion_metadata = generate_assertion_metadata(assertions["public"])

chain_name = BLOCKCHAINS[self._chain_id()]["name"]
content_asset_storage_address = self._get_asset_storage_address(
"ContentAssetStorage"
)

if token_amount is None:
token_amount = int(
self._get_bid_suggestion(
chain_name,
blockchain_id,
epochs_number,
public_assertion_metadata["size"],
content_asset_storage_address,
Expand All @@ -153,7 +215,7 @@ def create(
)

current_allowance = self.get_current_allowance()
if (is_allowance_increased := current_allowance < token_amount):
if is_allowance_increased := current_allowance < token_amount:
self.increase_allowance(token_amount)

try:
Expand Down Expand Up @@ -183,7 +245,7 @@ def create(

assertions_list = [
{
"blockchain": chain_name,
"blockchain": blockchain_id,
"contract": content_asset_storage_address,
"tokenId": token_id,
"assertionId": public_assertion_id,
Expand All @@ -195,7 +257,7 @@ def create(
if content.get("private", None):
assertions_list.append(
{
"blockchain": chain_name,
"blockchain": blockchain_id,
"contract": content_asset_storage_address,
"tokenId": token_id,
"assertionId": MerkleTree(
Expand All @@ -213,15 +275,15 @@ def create(
operation_id = self._publish(
public_assertion_id,
assertions["public"],
chain_name,
blockchain_id,
content_asset_storage_address,
token_id,
DEFAULT_HASH_FUNCTION_ID,
)["operationId"]
operation_result = self.get_operation_result(operation_id, "publish")

return {
"UAL": format_ual(chain_name, content_asset_storage_address, token_id),
"UAL": format_ual(blockchain_id, content_asset_storage_address, token_id),
"publicAssertionId": public_assertion_id,
"operation": {
"operationId": operation_id,
Expand Down Expand Up @@ -265,7 +327,8 @@ def update(
content_type: Literal["JSON-LD", "N-Quads"] = "JSON-LD",
) -> dict[str, HexStr | dict[str, str]]:
parsed_ual = parse_ual(ual)
content_asset_storage_address, token_id = (
blockchain_id, content_asset_storage_address, token_id = (
parsed_ual["blockchain"],
parsed_ual["contract_address"],
parsed_ual["token_id"],
)
Expand All @@ -278,8 +341,6 @@ def update(
).root
public_assertion_metadata = generate_assertion_metadata(assertions["public"])

chain_name = BLOCKCHAINS[self._chain_id()]["name"]

if token_amount is None:
agreement_id = self.get_agreement_id(
content_asset_storage_address, token_id
Expand All @@ -297,7 +358,7 @@ def update(

token_amount = int(
self._get_bid_suggestion(
chain_name,
blockchain_id,
epochs_left,
public_assertion_metadata["size"],
content_asset_storage_address,
Expand All @@ -306,11 +367,11 @@ def update(
)["bidSuggestion"]
)

token_amount -= agreement_data.tokensInfo[0]
token_amount -= agreement_data.tokens[0]
token_amount = token_amount if token_amount > 0 else 0

current_allowance = self.get_current_allowance()
if (is_allowance_increased := current_allowance < token_amount):
if is_allowance_increased := current_allowance < token_amount:
self.increase_allowance(token_amount)

try:
Expand All @@ -329,7 +390,7 @@ def update(

assertions_list = [
{
"blockchain": chain_name,
"blockchain": blockchain_id,
"contract": content_asset_storage_address,
"tokenId": token_id,
"assertionId": public_assertion_id,
Expand All @@ -341,7 +402,7 @@ def update(
if content.get("private", None):
assertions_list.append(
{
"blockchain": chain_name,
"blockchain": blockchain_id,
"contract": content_asset_storage_address,
"tokenId": token_id,
"assertionId": MerkleTree(
Expand All @@ -359,15 +420,15 @@ def update(
operation_id = self._update(
public_assertion_id,
assertions["public"],
chain_name,
blockchain_id,
content_asset_storage_address,
token_id,
DEFAULT_HASH_FUNCTION_ID,
)["operationId"]
operation_result = self.get_operation_result(operation_id, "update")

return {
"UAL": format_ual(chain_name, content_asset_storage_address, token_id),
"UAL": format_ual(blockchain_id, content_asset_storage_address, token_id),
"publicAssertionId": public_assertion_id,
"operation": {
"operationId": operation_id,
Expand Down Expand Up @@ -638,22 +699,21 @@ def extend_storing_period(
token_amount: Wei | None = None,
) -> dict[str, UAL | dict[str, str]]:
parsed_ual = parse_ual(ual)
content_asset_storage_address, token_id = (
blockchain_id, content_asset_storage_address, token_id = (
parsed_ual["blockchain"],
parsed_ual["contract_address"],
parsed_ual["token_id"],
)

if token_amount is None:
chain_name = BLOCKCHAINS[self._chain_id()]["name"]

latest_finalized_state = self._get_latest_assertion_id(token_id)
latest_finalized_state_size = self._get_assertion_size(
latest_finalized_state
)

token_amount = int(
self._get_bid_suggestion(
chain_name,
blockchain_id,
additional_epochs,
latest_finalized_state_size,
content_asset_storage_address,
Expand All @@ -678,14 +738,13 @@ def add_tokens(
token_amount: Wei | None = None,
) -> dict[str, UAL | dict[str, str]]:
parsed_ual = parse_ual(ual)
content_asset_storage_address, token_id = (
blockchain_id, content_asset_storage_address, token_id = (
parsed_ual["blockchain"],
parsed_ual["contract_address"],
parsed_ual["token_id"],
)

if token_amount is None:
chain_name = BLOCKCHAINS[self._chain_id()]["name"]

agreement_id = self.get_agreement_id(
content_asset_storage_address, token_id
)
Expand All @@ -707,7 +766,7 @@ def add_tokens(

token_amount = int(
self._get_bid_suggestion(
chain_name,
blockchain_id,
epochs_left,
latest_finalized_state_size,
content_asset_storage_address,
Expand Down Expand Up @@ -738,14 +797,13 @@ def add_update_tokens(
token_amount: Wei | None = None,
) -> dict[str, UAL | dict[str, str]]:
parsed_ual = parse_ual(ual)
content_asset_storage_address, token_id = (
blockchain_id, content_asset_storage_address, token_id = (
parsed_ual["blockchain"],
parsed_ual["contract_address"],
parsed_ual["token_id"],
)

if token_amount is None:
chain_name = BLOCKCHAINS[self._chain_id()]["name"]

agreement_id = self.get_agreement_id(
content_asset_storage_address, token_id
)
Expand All @@ -765,7 +823,7 @@ def add_update_tokens(

token_amount = int(
self._get_bid_suggestion(
chain_name,
blockchain_id,
epochs_left,
unfinalized_state_size,
content_asset_storage_address,
Expand All @@ -788,8 +846,6 @@ def add_update_tokens(
"operation": {"status": "COMPLETED"},
}

_owner = Method(BlockchainRequest.owner_of)

def get_owner(self, ual: UAL) -> Address:
token_id = parse_ual(ual)["token_id"]

Expand Down
54 changes: 41 additions & 13 deletions dkg/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,51 @@
)

BLOCKCHAINS = {
2043: {
"name": "otp",
"hubAddress": "0x5fA7916c48Fe6D5F1738d12Ad234b78c90B4cAdA"
"development": {
"hardhat1:31337": {
"hub": "0x5FbDB2315678afecb367f032d93F642f64180aa3",
"rpc": "http://localhost:8545",
},
2160: {
"name": "otp",
"hubAddress": "0x833048F6e6BEa78E0AAdedeCd2Dc2231dda443FB"
"hardhat2:31337": {
"hub": "0x5FbDB2315678afecb367f032d93F642f64180aa3",
"rpc": "http://localhost:9545",
},
20430: {
"name": "otp",
"hubAddress": "0xBbfF7Ea6b2Addc1f38A0798329e12C08f03750A6"
"otp:2043": {
"hub": "0x7585a99C5C150a08f5CDeFD16465C6De8D41EbbD",
"rpc": "http://parachain-alphanet-02.origin-trail.network:9933",
},
31337: {
"name": "hardhat",
"hubAddress": "0x5FbDB2315678afecb367f032d93F642f64180aa3"
},
"devnet": {
"otp:2160": {
"hub": "0x833048F6e6BEa78E0AAdedeCd2Dc2231dda443FB",
"rpc": "https://lofar-tm-rpc.origin-trail.network",
},
}
"gnosis:10200": {
"hub": "0xD2bA102A0b11944d00180eE8136208ccF87bC39A",
"rpc": "https://rpc.chiadochain.net",
"gas_price_oracle": "https://blockscout.chiadochain.net/api/v1/gas-price-oracle",
},
},
"testnet": {
"otp:20430": {
"hub": "0xBbfF7Ea6b2Addc1f38A0798329e12C08f03750A6",
"rpc": "https://lofar-testnet.origin-trail.network",
},
"gnosis:10200": {
"hub": "0xC06210312C9217A0EdF67453618F5eB96668679A",
"rpc": "https://rpc.chiadochain.net",
"gas_price_oracle": "https://blockscout.chiadochain.net/api/v1/gas-price-oracle",
},
},
"mainnet": {
"otp:2043": {
"hub": "0x5fA7916c48Fe6D5F1738d12Ad234b78c90B4cAdA",
"rpc": "https://astrosat-parachain-rpc.origin-trail.network",
},
},
}

DEFAULT_GAS_PRICE_GWEI = 100

DEFAULT_HASH_FUNCTION_ID = 1
DEFAULT_SCORE_FUNCTION_ID = 1
Expand Down
Loading

0 comments on commit 25092f5

Please sign in to comment.