Source code for datatrails_receipt_scitt.khipureceipt

DataTrails Khipu event specifics
from eth_utils import to_checksum_address

from . import trie_alg
from .attribute_decoder import (

from .receipt import bto3339, u256touuid, Receipt

[docs] class KhipuReceiptMalformedAttributes(ValueError): """ The receipt encoding of the datatrails attributes is malformed """
EXTRA_PARAMETERS = ["monotonic_version"] APPLICATION_PARAMETERS = trie_alg.APPLICATION_PARAMETERS + EXTRA_PARAMETERS MANIFEST_ELEMENTS = "who_declared who_accepted essentials attribute_kindnames attribute_values when".split() ATTRIBUTE_KINDNAMES = "attribute_kindnames" ATTRIBUTE_VALUES = "attribute_values" ESSENTIALS = "essentials" ESSENTIALS_CREATOR = "creator" ESSENTIALS_KHIPUIDENTITY = "khipuIdentity" ESSENTIALS_ASSETIDENTITY = "assetIdentity" WHO_ISSUER = 0 WHO_SUBJECT = 1 WHO_DISPLAY_NAME = 2 WHO_EMAIL = 3 WHEN_DECLARED = 0 WHEN_ACCEPTED = 1 WHEN_COMMITTED = 2 def _principal_from_rawstorage(rawstorage): """ :param rawstorage: the 4 element list of strings representing a principal """ return { "issuer": rawstorage[WHO_ISSUER].decode("utf-8"), "subject": rawstorage[WHO_SUBJECT].decode("utf-8"), "display_name": rawstorage[WHO_DISPLAY_NAME].decode("utf-8"), "email": rawstorage[WHO_EMAIL].decode("utf-8"), } def _whens_from_rawstorage(rawstorage): """ :param rawstorage: the 3 element list of slot values from the 'when' proof """ # datatrails_simplehash.V1_FIELDS (in defines constants for these dict # keys these in alignment with the public datatrails events api return { "timestamp_declared": bto3339(rawstorage[WHEN_DECLARED]), "timestamp_accepted": bto3339(rawstorage[WHEN_ACCEPTED]), # scale down by 1000,000,000. raft block time stamps are in nanoseconds # and we need seconds to do the RFC 3339 conversion "timestamp_committed": bto3339(rawstorage[WHEN_COMMITTED], scale=1000000000), }
[docs] class KhipuReceipt(Receipt): """ This class adds khipu specific receipt handling. See :class:`Receipt` for a general description. """
[docs] def verify(self, worldroot: str = None): """Verify the named proofs * If the worldroot is supplied, the presence of the contract storage account is verified If no parameters are supplied this method simple verifies the storage proofs are consistent with the storage roots in the proof itself. :param worldroot: ethereum world state root from the block header """ super().verify(MANIFEST_ELEMENTS, worldroot)
[docs] def decode(self): """decode the application values from the proof""" # ensure we have the proofs from the contents collected if not self.namedproofs.proofs: self.namedproofs.collect_proofs(*MANIFEST_ELEMENTS) self.namedproofs.decode() # Now use DataTrails API assumptions to rebuild the event and asset attributes map kindnames = self.namedproofs.decoded(ATTRIBUTE_KINDNAMES).arrays values = self.namedproofs.decoded(ATTRIBUTE_VALUES).arrays if len(kindnames) != len(values): raise KhipuReceiptMalformedAttributes( "number of names inconsistent with number of values" ) assetattributes = {} eventattributes = {} for kindname, rlpvalue in zip(kindnames, values): kind, name = decode_attribute_key(kindname) value = decode_attribute_value(rlpvalue) if kind == AttributeType.ASSET: assetattributes[name] = value elif kind == AttributeType.EVENT: eventattributes[name] = value else: raise KhipuReceiptMalformedAttributes( f"unsupported kind '{kind}' for attribute '{name}'" ) # Note we don't currently include the aggregate sharing policy # attributes in the receipt. We may do in future. essentials = self.namedproofs.decoded(ESSENTIALS) creator = to_checksum_address( essentials.value(ESSENTIALS_CREATOR) ) # aka from address eventUUID = u256touuid(essentials.value(ESSENTIALS_KHIPUIDENTITY)) assetUUID = u256touuid(essentials.value(ESSENTIALS_ASSETIDENTITY)) # TODO: missing the khipu schema version number 'monotonicversion' who_declared = self.namedproofs.decoded("who_declared") who_accepted = self.namedproofs.decoded("who_accepted") whens = _whens_from_rawstorage(self.namedproofs.decoded("when").values) # Note: this dict is aligned with the constants and event structure we # work with in the datatrails-simplehash-python package. see # datatrails_simplehash.V1_FIELDS (in event = { "identity": f"assets/{assetUUID}/events/{eventUUID}", "asset_identity": f"assets/{assetUUID}", "from": creator, "principal_declared": _principal_from_rawstorage(who_declared.arrays), "principal_accepted": _principal_from_rawstorage(who_accepted.arrays), "asset_attributes": assetattributes, "event_attributes": eventattributes, } event.update(whens) return event