Skip to content

Commit

Permalink
Add support for asset fingerprint (CIP14) (#294)
Browse files Browse the repository at this point in the history
* Added extended signing key support for cip8

* Fixed unused imports, flake8 checks pass.

* Fixed mypy error for overloaded variable

* Remove extraneous parameter for verify

* Added ByteString to _restored_typed_primitive

* Added type checking

* Added support for CIP 14

* Added support for ScriptHash and AssetName

* Add import to cips and docs

---------

Co-authored-by: Niels Mündler <[email protected]>
  • Loading branch information
theeldermillenial and nielstron authored Jan 10, 2024
1 parent 8cbf815 commit 3d27786
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 0 deletions.
5 changes: 5 additions & 0 deletions docs/source/api/pycardano.cip.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,8 @@ Implementation of Cardano Improvement Proposals (CIPs)
:members:
:undoc-members:
:show-inheritance:

.. automodule:: pycardano.cip.cip14
:members:
:undoc-members:
:show-inheritance:
1 change: 1 addition & 0 deletions pycardano/cip/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# flake8: noqa

from .cip8 import *
from .cip14 import *
41 changes: 41 additions & 0 deletions pycardano/cip/cip14.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from typing import Union

from nacl.encoding import RawEncoder
from nacl.hash import blake2b
from pycardano.crypto.bech32 import encode
from pycardano.hash import ScriptHash
from pycardano.transaction import AssetName


def encode_asset(
policy_id: Union[ScriptHash, bytes, str], asset_name: Union[AssetName, bytes, str]
) -> str:
"""Implementation of CIP14 asset fingerprinting
This function encodes the asset policy and name into an asset fingerprint, which is
bech32 compliant.
For more information:
https://developers.cardano.org/docs/governance/cardano-improvement-proposals/cip-0014/
Args:
policy_id: The asset policy as `ScriptHash`, `bytes`, or a hex `str`
asset_name: The asset name as `AssetName`, `bytes`, or a hex `str`
"""
if isinstance(policy_id, str):
policy_id = bytes.fromhex(policy_id)
elif isinstance(policy_id, ScriptHash):
policy_id = policy_id.payload

if isinstance(asset_name, str):
asset_name = bytes.fromhex(asset_name)
elif isinstance(asset_name, AssetName):
asset_name = asset_name.payload

asset_hash = blake2b(
policy_id + asset_name,
digest_size=20,
encoder=RawEncoder,
)

return encode("asset", asset_hash)
72 changes: 72 additions & 0 deletions test/pycardano/test_cip14.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import pytest

from pycardano.cip.cip14 import encode_asset
from pycardano.hash import ScriptHash
from pycardano.transaction import AssetName


@pytest.mark.parametrize(
"input_types", [(str, str), (bytes, bytes), (ScriptHash, AssetName)]
)
@pytest.mark.parametrize(
"asset",
[
{
"policy_id": "7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373",
"asset_name": "",
"asset_fingerprint": "asset1rjklcrnsdzqp65wjgrg55sy9723kw09mlgvlc3",
},
{
"policy_id": "7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc37e",
"asset_name": "",
"asset_fingerprint": "asset1nl0puwxmhas8fawxp8nx4e2q3wekg969n2auw3",
},
{
"policy_id": "1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df209",
"asset_name": "",
"asset_fingerprint": "asset1uyuxku60yqe57nusqzjx38aan3f2wq6s93f6ea",
},
{
"policy_id": "7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373",
"asset_name": "504154415445",
"asset_fingerprint": "asset13n25uv0yaf5kus35fm2k86cqy60z58d9xmde92",
},
{
"policy_id": "1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df209",
"asset_name": "504154415445",
"asset_fingerprint": "asset1hv4p5tv2a837mzqrst04d0dcptdjmluqvdx9k3",
},
{
"policy_id": "1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df209",
"asset_name": "7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373",
"asset_fingerprint": "asset1aqrdypg669jgazruv5ah07nuyqe0wxjhe2el6f",
},
{
"policy_id": "7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373",
"asset_name": "1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df209",
"asset_fingerprint": "asset17jd78wukhtrnmjh3fngzasxm8rck0l2r4hhyyt",
},
{
"policy_id": "7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373",
"asset_name": "0000000000000000000000000000000000000000000000000000000000000000",
"asset_fingerprint": "asset1pkpwyknlvul7az0xx8czhl60pyel45rpje4z8w",
},
],
)
def test_encode_asset(asset, input_types):
if isinstance(input_types[0], bytes):
policy_id = bytes.fromhex(asset["policy_id"])
asset_name = bytes.fromhex(asset["asset_name"])
elif isinstance(input_types[0], str):
policy_id = asset["policy_id"]
asset_name = asset["asset_name"]

if isinstance(input_types[0], ScriptHash):
policy_id = ScriptHash(policy_id)
asset_name = AssetName(asset_name)

fingerprint = encode_asset(
policy_id=asset["policy_id"], asset_name=asset["asset_name"]
)

assert fingerprint == asset["asset_fingerprint"]

0 comments on commit 3d27786

Please sign in to comment.