API

Module for decoding on chain attributes into the format returned from the event api

class datatrails_receipt_scitt.attribute_decoder.AttributeType(value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None)[source]

Attribute type is the type of attributes supported by DataTrails events

datatrails_receipt_scitt.attribute_decoder.decode_attribute_key(kind_name: bytes) tuple[AttributeType, str][source]

Decodes the attribute kind<->name pairing into the attribute kind and keys

Parameters:

kind_name (str) – the rlp encoded attribute kind concatenated with the attribute key encoded as a hex string, e.g. 0x8767697261666665…

Returns:

a tuple of (attribute type, attribute key)

datatrails_receipt_scitt.attribute_decoder.decode_attribute_value(attrvalue: bytes) str | list | dict[source]

decode an rlp encoded attribute value

Parameters:

hex (str) – an rlp encoded hexadecimal string, e.g. 0xe5866c6973747632cecd87676972…

Returns:

one of:

  • a string value

  • a dictionary value

  • a list of dictionary values

the rlp encoded list value is of the shape:

[][][]string {
  [
    "listv2"
  ],
  [
    [
      [
        "giraffe", <- key
        "tall" <- value
      ],
    ],
  ],
  [
    [
      [
        "elephant", <- key
        "big" <- value
      ],
    ],
  ]
}

the rlp encoded dict value is of the shape:

[][]string {
  [
    [
      "dictv2",
    ],
    [
      "giraffe", <- key
      "tall" <- value
    ],
    [
      "elephant", <- key
      "big" <- value
    ]
  ]
}

The EIP1186NamedProofs trie algorithm defines three proof metadata formats.

Note that the proofs are always for the raw storage values. Those are proven to be ‘on-chain’ regardless of the metadata. The metadata provides for round tripping between the raw storage values and its application level representation.

The three formats defined here are intrinsic to this trie algorithm. They are defined to be application neutral. They focus on recovering the proven application values from the receipts without :192 recourse to application domain knowledge. Just knowledge of the EVM and the solidity compiler abi.

Applications (including DataTrails) are free to define new element types but SHOULD only do so if the intrinsics are insufficient.

In the case of extended types, The app_id and the app_content_ref properties in the application_parameters in the receipt MUST reference the information necessary to interpret the proven values.

In many cases we would expect the raw proof values to be sufficient from an evidentiary perspective.

class datatrails_receipt_scitt.elementmetadata.ByteArrays(storageproofs: list, metadata: dict)[source]

Helper for eip1186:3:loba

The list of proofs in storage proof proves the presence of a list of byte arrays. The metadata contains a slot count for each byte array.

For example

metadata: {
    slots: [3, 2, 5],
    lenlasts: [28, 3, 32]
}

Describes 3 distinct byte arrays. The first consumes the values for the first 3 proofs, the second proof values 3 & 4, and the last takes the remaining 5 proof values.

The last slot of each respective array has 28 bytes, 3 bytes and finally exactly 32 bytes

class datatrails_receipt_scitt.elementmetadata.FieldValues(storageproofs: list, metadata: dict)[source]

Helper for eip1186:2:fv

The list of proofs in storage proof proves the presence of an array of storage slots backing a solidity ABI structure. The metadata defines the variable field structure in those slots (but does not currently contain the original type info)

For example:

metadata: {
    fields: [
        { "name": "foo", "slot": 0, "offset": 0, "size": 2},
        { "name": "bar", "slot": 0, "offset": 2, "size": 4},
        { "name": "baz", "slot": 1, "offset": 0, "size": 32}
    }
}

Defines the variables foo, bar and baz. foo and bar are packed into the first slot. Due to occupying a full 32 byte slot, baz.

Notes

a) In the current DataTrails usage fields occupied by nested slots are typically omitted and dealt with as a special case (who & when). We may in future allow size to be a multiple of 32 to allow for inline nested structs.

b) the offset is from the low register address, which frustratingly is at the right end of the word. Eg the offsets should actually be visualized like this. (We intend to change the backend to make this more intuitive)

|31|30 … 2|1|0|

c) we plan to add the original solidity type names in a future backend release.

fields()[source]

return the list of field names

value(name: str)[source]

return the value of the field

exception datatrails_receipt_scitt.elementmetadata.MetadataError[source]

Raised when there is an unexpected formatting or content issue with the metadata.

class datatrails_receipt_scitt.elementmetadata.SlotArray(storageproofs: list, lenlast: int = None)[source]

Helper for eip1186:1:sa

After construction the concatenation of all slot values is available on .value The individual slot values are available in .values

No extra metadata is required for this type. However, if the number of significant bytes for the last slot is known it can be supplied via the lenlast constructor param. This does not impact the proof, that is for the full slot contents regardless of storage layout within that slot.

This accommodates:
  • a storage proof for a solidity dynamic array of bytes (string or bytes)

  • a storage proof for a struct whose fields are all uint256

# code based on example found: # https://web3py.readthedocs.io/en/v5/web3.eth.html

# for imports we need to do the following pip installs: # trie

exception datatrails_receipt_scitt.ethproofs.VerifyFailed[source]

raised if a proof verification operation fails

datatrails_receipt_scitt.ethproofs.verify_eth_account_proof(account: str, ethproof: dict, root: HexBytes)[source]

verifies the given account proof with the given root

Parameters:
  • proof (dict) – the merkle proof as per the response from eth_getProof

  • root (HexBytes) – the state root of the block to verify the account proof against

datatrails_receipt_scitt.ethproofs.verify_eth_storage_proof(ethproof)[source]

verifies the given account proof with the given root

Parameters:

ethproof – the merkle proof as per the response from eth_getProof

Module for execptions for datatrails receipt scitt

exception datatrails_receipt_scitt.exceptions.InvalidAttributeType[source]

Raised when the attribute type, of an attribute is not an accepted type

DataTrails Khipu event specifics

class datatrails_receipt_scitt.khipureceipt.KhipuReceipt(contents, serviceparams=None)[source]

This class adds khipu specific receipt handling. See Receipt for a general description.

decode()[source]

decode the application values from the proof

verify(worldroot: str = None)[source]

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.

Parameters:

worldroot – ethereum world state root from the block header

exception datatrails_receipt_scitt.khipureceipt.KhipuReceiptMalformedAttributes[source]

The receipt encoding of the datatrails attributes is malformed

Support decoding of the receipt response from the DataTrails /v1/notary/receipts end point

The format of the receipt follows this draft standard draft-birkholz-scitt-receipts-02

draft-birkholz-scitt-receipts-02 [3. Generic Receipt Structure]:

[ protected, contents ]

We define the DataTrails tree algorithm ‘EIP1186NamedSlotProofs’ based on EIP1186 formatted merkle proofs

The protected field is dictated by the standard. The contents field is define by EIP1186NamedSlotProofs

datatrails_receipt_scitt.receiptdecoder.receipt_trie_alg_contents(receipt: bytes) Tuple[dict, bool][source]

decode the protected header, the signature and the tree-alg contents from the receipt.

The semantics of the contents are defined by the EIP1186NamedSlotProofs tree alg.

Parameters:

receipt (str) – base64 encoded CBOR, or CBOR Cose Sign1 receipt value obtained from the receipts api

Returns:

a tuple of proof and whether the proof is public or permissioned

datatrails_receipt_scitt.receiptdecoder.receipt_verify_envelope(key, sign_protected: bytes, contents: bytes, signature: bytes)[source]

Verify the signature and protected header for the partially decoded receipt

See unittests/wellknownkey.py for why this is only by way of example and not required.

This does _NOT_ verify the contents according to the trie alg, simply that the contents, treated as an opaque blob, have been signed by the trusted service, along with the protected headers.

There are currently no unprotected headers defined

Parameters:

sign_protected (bytes) – protected headers identifying the service and the

trie alg, decoded from the receipt. :param bytes signature: trust services signature over the protected header and the content

Constants and utilities intrinsic to the EIP1186NamedProofs trie alg