Provenance
  • Proof Points
  • Framework
  • Principles
  • Integrity Council
  • Trusted Verifiers
  • Inspector
  • Developers
  • Specification
  • Get Involved

Provenance Proof Points v1.0

Specification

  1. Proof Point Document Format
  2. Proof Point Identifier
    1. Generating the Proof Point Identifier
  3. The ProofPointRegistry Smart Contract
  4. Proof Point Issuer
  5. Issue
  6. Commit
  7. Revoke
  8. Validate
  9. Locating the ProofPointRegistry

The Provenance Proof Point system is an implementation of the W3C Verifiable Credentials specification, with an extension to ensure there is a public, trustless append-only log of all Proof Points ever issued and to enable the authenticity and revocation status of a presented Proof Point to be checked using a smart contract on the Ethereum blockchain.

In general the system supports the following functionality:

  • A Proof Point is a claim by an issuer that a given property or relation is held by one or more subjects
  • The Proof Point is represented by a self-describing JSON document that meets the W3C Verifiable Credentials specification and an associated blockchain record which serves to authenticate (or by its absence revoke) the document
  • The issuer is represented by an Ethereum address, or a did:web identifier.
  • The subject may be represented by any URI
  • The system supports four functions
    1. issue by which an issuer may create and publish a new Proof Point
    2. commit by which an issuer may create and publish a new Proof Point that cannot be revoked
    3. revoke by which the issuer of an issued Proof Point may revoke it, meaning that is it no longer valid and will subsequently fail the validate process.
    4. validate by which anyone presented with a Proof Point may verify that it was issued or commited by the issuer and has not subsequently been revoked. Note that a valid Proof Point is not necessarily true just as any signed statement is not necessarily true.
  • A Proof Point can be issued or validated by anyone with access to the Ethereum network, and may be revoked only by the issuer.
  • Proof Points are tamper proof in that modifying the content of a valid Proof Point invalidates it.
  • There is a public, trustless, append-only log of all Proof Points that have ever been issued or commited

1. Proof Point Document Format

The JSON document part of the Proof Point is an implementation of the W3C Verifiable Credentials with a special, Provenance specific proof type as defined here.

{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://open.provenance.org/ontology/ptf/v2"
  ],
  "type": ["VerifiableCredential", "<type>"],
  "issuer": "<issuer>",
  "validFrom": "<valid-from-date>",
  "validUntil": "<valid-until-date>",
  "credentialSubject": [
    {
      "id": "<subject>",
      <type-specific-data>
    }
    ...
  ], ,
  "proof": {
    "type": "ProvenanceProofType1",
    "registryRoot": <registry-root>,
    "proofPurpose": "assertionMethod",
    "verificationMethod": "<issuer>"
  }
}
Token Meaning
type An IRI representing the type of claim being made. This defines the meaning of the claim as well as defining what fields should be expected in the type-specific-data
issuer The Ethereum address of the issuer of the claim. This is the account that must be used to issue, commit and revoke the claim. The address may be represented either directly or using the did:web URI scheme. See Proof Point Issuer
valid-from-date Optional, the date from which the claim is valid, in RFC3339 format. If present this will be checked as part of validation
valid-until-date Optional, the date until which the claim is valid, in RFC3339 format. If present this will be checked as part of validation
subject A URL identifying the subject of the claim. For business, product and ingredient claims it could be the address of the corresponding page within provenance.org. A claim with multiple subjects such as a connection claim should include one credentialSubject entry for each subject
type-specific-data Data fields specific to the type which serve to further specify the meaning of the claim
registry-root The Ethereum address of the RegistryRoot instance which indirectly specifies the ProofPointRegistry contract that should be used to issue, commit, revoke and validate this claim. See Locating the Claims Registry.

Note The method field of the proof is what makes this W3C Verifiable Credential a Proof Point. The identifier https://open.provenance.org/ontology/ptf/v2#ProvenanceProofType1 specifies the proof method defined in this document.

An example claim document:

{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://open.provenance.org/ontology/ptf/v2"
  ],
  "type": ["VerifiableCredential", "CertificationClaim"],
  "issuer": "0x8F36fd828D18a060CF4523DE69eE9Ddc3ec23135",
  "validFrom": "2018-01-01T00:00:00",
  "validUntil": "2020-01-01T00:00:00",
  "credentialSubject": [
    {
      "id": "https://www.provenance.org/users/great-beer-co",
      "certification": "https://provenance.org/ontology/ptf/v2/certifications/ava-certified-vegetarian"
    }
  ],
  "proof": {
    "type": "ProvenanceProofType1",
    "registryRoot": "0x2756e9d20c621A0eF9F4fF58c9809DD5F4c2dca1",
    "proofPurpose": "assertionMethod",
    "verificationMethod": "0x8F36fd828D18a060CF4523DE69eE9Ddc3ec23135"
  }
}

2. Proof Point Identifier

Each Proof Point has a unique identifier (or ID), which is a fixed length string that can be generated from the Proof Point JSON document using the following method. The ID is used to represent the Proof Point when interacting with the Proof Point Registry Smart Contract and may also be a convenient way to represent the Proof Point in other situations.

The Proof Point ID is designed to be a valid IPFS digest. When an issuer issues a Proof Point they have the option to store the Proof Point document on IPFS. In this case it is possible to recover the Proof Point document from the Proof Point ID using an IPFS lookup.

2.1. Generating the Proof Point Identifier

The ID is generated from the Proof Point JSON document according to to the following method:

  1. Canonicalize the document according to the draft-rundgren-json-canonicalization-scheme. For example, by using this NPM package
  2. Compute the base 58 encoding of the multihash encoding of the 32 byte SHA-256 hash of the canonicalized document. Note that this the IPFS digest you will get if you add the file to IPFS and specify the sha2-256 hash method: ipfs add --hash sha2-256 <file>. The result is the Proof Point ID.

3. The ProofPointRegistry Smart Contract

The ProofPointRegistry smart contract is a singleton smart contract on the Ethereum blockchain that is used to support Proof Point functionality. The following is the API of the contract. We will see how it is used in later sections.

contract ProofPointRegistry {

    event Issued(address _issuer, bytes _claim);
    event Committed(address _issuer, bytes _claim);
    event Revoked(address _issuer, bytes _claim);
    
    function issue(bytes memory _claim);

    function commit(bytes memory _claim);

    function revoke(bytes memory _claim);

    function validate(address _issuer, bytes memory _claim) view returns(bool);
}

4. Proof Point Issuer

Each Proof Point declares an issuer which is an Ethereum address represented either directly or using the did:web protocol. Where the issuer is represented using a did:web URI it will be necessary to resolve this to an Ethereum address in order to either issue, commit or validate it. For more information on how to do this please see the did:web Decentralized Identifier Method Specification

5. Issue

To issue a new valid Proof Point the following process is used:

Note This process involves a blockchain write, so can only be carried out by an issuer account with Ether funds and the process is subject to the normal block finalization delay.

  1. Determine the <issuer>, <subject>, <type>, <type-specific-data>, <valid-from-date> (optional), <valid-until-date> (optional) and <registry-root>. The <issuer> must be an Ethereum account that you control. The issued claim will only be valid between the <valid-from-date> and <valid-until-date> if present.
  2. Construct a JSON document according to the Claim Data Format
  3. Compute the Proof Point ID
  4. (Optional) Store the canonicalized Proof Point document on IPFS
  5. Locate the ProofPointRegistry
  6. Using the <issuer> account, call the issue method of the ProofPointRegistry contract with the ID generated in 3.

The document (both canonical, pre-canonical and ID form) is now a valid Proof Point and may be published or transmitted to a holder or validator.

6. Commit

A commitment is a Proof Point that cannot be revoked. Once issued it is valid forever (within the validFrom to validUntil time range). To commit a new valid Proof Point the process for issuing a claim is followed except that the commit method of the ProofPointRegistry contract is called, instead of the issue method.

Note that this process involves a blockchain write, so can only be carried out by an issuer account with Ether funds and the process is subject to the normal block finalization delay.

7. Revoke

To revoke a valid Proof Point the following process is used:

Note This process involves a blockchain write, so can only be carried out by an issuer account with Ether funds and the process is subject to the normal block finalization delay.

Note Only the issuer can revoke a Proof Point

Note Revoking a commited claim has no effect

  1. Start with the JSON document that was issued
  2. Compute the Proof Point ID
  3. Locate the ProofPointRegistry
  4. Using the issuer account, call the revoke method of the ProofPointRegistry contract with the ID computed in 2.

The Proof Point is no longer valid in any form.

8. Validate

To check the validity of a given Proof Point the following process is used:

Note This process involves a blockchain read, but not a write, so no Ether funds are required to perform this process.

  1. Start with the JSON document that you want to validate. This may have been directly transmitted to you, or may be recovered from the ID using an IPFS lookup.
  2. If the validFrom field is present and is in the future then the claim is invalid
  3. If the validUntil field is present and is in the past then the claim is invalid
  4. Compute the Proof Point ID if you don't already have it.
  5. Locate the ProofPointRegistry
  6. Call the validate method of the ProofPointRegistry contract with the <issuer> and the ID computed in 5. If the return value is true then the Proof Point is valid, otherwise it is invalid.

9. Locating the ProofPointRegistry

The ProofPointRegistry is a singleton smart contract on the Ethereum blockchain. In order to enable upgrades and bug fixes the Eternal Storage Pattern is used. This means that the address of the contract can change over time. Therefore the location of the ProofPointRegistry is not directly recorded in a claim. Instead the claim records registryRoot; the address of a permanent contract that can be used to look up the current address of the ProofPointRegistry.

The registryRoot is the address of a contract with the following API:

contract RegistryRoot {
    function getOwner() view returns(address);
}

In order to resolve the registryRoot to the address of the ProofPointRegistry the following process is used:

  1. Call the getOwner method of the RegistryRoot contract at <registry-root> to get the address for the current implementation of the ProofPointRegistry
  2. Use the ProofPointRegistry at the specified address for all ProofPointRegistry interactions
Get in touch with the team: open@provenance.org.
© 2013- Project Provenance Ltd. Content on this subdomain is available under these licenses.
PROVENANCE® is a registered trade mark in the EU and US of Project Provenance Ltd.