Welcome to the new Provenance Blockchain developer documentation portal!
logo
The metadata service provides a system for referencing off-chain information. It can be used to record and validate information as well as the processes that create the information.
One notable use case is that Figure uses this module in order to create scopes for loans, representing loans as Real World Assets on the Provenance Blockchain.
ConceptsSummaryEntriesSpecificationsMetadata AddressesMetadataAddress Example ImplementationsMetadataAddress General GuidelinesIndexesSigning RequirementsScope Value Owner Address RequirementsSmart Contract RequirementsWith Party Rollup RequiredWriting or Deleting a Scope With Party RollupWriting a Session With Party RollupWriting a Record With Party RollupDeleting a Record With Party RollupWithout Party Rollup RequiredWriting or Deleting a Scope Without Party RollupWriting a Session Without Party RollupWriting a Record Without Party RollupDeleting a Record Without Party RollupStateSummaryEntriesScopesScope Keys (Metadata Addresses)Scope ValuesScope IndexesSessionsSession Keys (Metadata Addresses)Session ValuesSession IndexesRecordsRecord Keys (Metadata Addresses)Record ValuesRecord IndexesSpecificationsScope SpecificationsScope Specification Keys (Metadata Addresses)Scope Specification ValuesScope Specification IndexesContract SpecificationsContract Specification Keys (Metadata Addresses)Contract Specification ValuesContract Specification IndexesRecord SpecificationsRecord Specification Keys (Metadata Addresses)Record Specification ValuesRecord Specification IndexesObject Store LocatorsObject Store Locator KeysObject Store Locator ValuesObject Store Locator IndexesMessagesSummaryEntriesMsg/WriteScopeRequestResponseExpected failuresMsg/DeleteScopeRequestResponseExpected failuresMsg/AddScopeDataAccessRequestResponseExpected failuresMsg/DeleteScopeDataAccessRequestResponseExpected failuresMsg/AddScopeOwnerRequestResponseExpected failuresMsg/DeleteScopeOwnerRequestResponseExpected failuresMsg/UpdateValueOwnersRequestResponseExpected failuresMsg/MigrateValueOwnerRequestResponseExpected failuresMsg/WriteSessionRequestResponseExpected failuresMsg/WriteRecordRequestResponseMsg/DeleteRecordRequestResponseExpected failuresSpecificationsMsg/WriteScopeSpecificationRequestResponseMsg/DeleteScopeSpecificationRequestResponseMsg/WriteContractSpecificationRequestResponseMsg/DeleteContractSpecificationRequestResponseMsg/AddContractSpecToScopeSpecRequestResponseMsg/DeleteContractSpecFromScopeSpecRequestResponseMsg/WriteRecordSpecificationRequestResponseMsg/DeleteRecordSpecificationRequestResponseObject Store LocatorsMsg/BindOSLocatorRequestResponseMsg/DeleteOSLocatorRequestResponseMsg/ModifyOSLocatorRequestResponseAccount DataMsg/SetAccountDataAuthz GrantsEventsSummaryGenericEventTxCompletedScopeEventScopeCreatedEventScopeUpdatedEventScopeDeletedSessionEventSessionCreatedEventSessionUpdatedEventSessionDeletedRecordEventRecordCreatedEventRecordUpdatedEventRecordDeletedScope SpecificationEventScopeSpecificationCreatedEventScopeSpecificationUpdatedEventScopeSpecificationDeletedContract SpecificationEventContractSpecificationCreatedEventContractSpecificationUpdatedEventContractSpecificationDeletedRecord SpecificationEventRecordSpecificationCreatedEventRecordSpecificationUpdatedEventRecordSpecificationDeletedObject Store LocatorEventOSLocatorCreatedEventOSLocatorUpdatedEventOSLocatorDeletedQueriesGithub LinkPrimary Data QueriesParamsScopeScopesAllSessionsSessionsAllRecordsRecordsAllOwnershipValueOwnershipSpecification QueriesScopeSpecificationScopeSpecificationsAllContractSpecificationContractSpecificationsAllRecordSpecificationsForContractSpecificationRecordSpecificationRecordSpecificationsAllGetByAddrObject Store Locator QueriesOSLocatorParamsOSLocatorOSLocatorsByURIOSLocatorsByScopeOSAllLocatorsAccount Data QueriesAccountDataRelated ResourcesParamsBase Module ParametersObject Store Locator ParametersMaxUriLengthRelated ResourcesUsage ContextSpecial Topics

Concepts

Summary

The metadata service manages three categories of data (entries, specifications, and object store locators) that define and reference off-chain information, using unique Metadata Addresses in bech32 format with specific byte array structures, specialized indexes for data association, and comprehensive signing requirements that vary based on party rollup configuration, value owner addresses, and smart contract usage within the Provenance blockchain ecosystem.

The metadata service manages things that define and reference off-chain data. There are three categories of things stored: entries, specifications, and object store locators. Each entry and specification has a unique Metadata Address that is often simply called its "id". Additionally, several indexes are created to help with linking and iterating over related messages.

Entries

The term "entries" refers to scopes, sessions, and records.
See Entries for details.

Specifications

The term "specifications" refers to scope specifications, contract specifications, and record specifications.
See Specifications for details.

Metadata Addresses

Entries and Specifications must each have a unique metadata address. These addresses are byte arrays that are commonly referered to as "ids". As strings, they should be represented using the bech32 address format. The addresses for the different messages have specific formats that help facilitate grouping and indexing. All addresses start with a single byte that identifies the type, and are followed by 16 bytes commonly called a UUID. Some address types contain other elements too.

MetadataAddress Example Implementations

GitHub Repository Examples:

MetadataAddress General Guidelines

  • As strings, the metadata addresses are represented using the bech32 address format.
  • The IdInfo messages defined in metadata.proto (e.g. RecordIdInfo) are used in response messages and contain a breakdown of a metadata address.
  • Variables that hold the addresses as byte arrays should end in _id.
  • Variables that hold the addresses as bech32 strings should end in _addr.
  • Variables that hold UUIDs as strings should use the standard UUID format and end in _uuid.
  • If a variable is a byte array that ends in _id, then it should be the full Metadata Address byte array.
  • String variables that end in _id should only be used in input messages. They should be flexible fields that can accept either the bech32 string version of the Metadata Address byte array, or a UUID in the standard UUID string format.
  • If a variable ends in _addr, then it should be the bech32 string version of the Metadata Address byte array.
  • If a variable ends in _uuid, then it should be a UUID in the standard UUID string format.
The exception to this is the byte array fields in the *IdInfo messages that represent the id broken into its various parts. For example, ScopeIdInfo.scope_id_scope_uuid represents the UUID portion of the scope_id, and is left as a byte array, but ScopeIdInfo.scope_uuid is the standard UUID string representation of those bytes.

Indexes

Indexes are specially formatted entries in the kvstore used to find associated things.
The keys contain all of the relevant information. They are byte arrays with three parts:
  • Type byte: A single byte representing the type of index.
  • Part 1: Address of the starting thing in the association.
  • Part 2: Address of the entry to find.
The values are always a single byte: 0x01.
The general use of them is to create a prefix using the type byte and part 1. Then use that prefix to iterate over all keys with that same prefix. During iteration, remove the prefix from the current entry's key in order to get the key of the thing to find.

Signing Requirements

Scopes have a require_party_rollup boolean field that dictates most signer requirements for a scope and all it's sessions and records.
There are also special signer considerations related to a scope's value_owner_address field.

Scope Value Owner Address Requirements

These requirements are applied regardless of a scope's require_party_rollup value. They are applied when writing new scopes, updating existing scopes, and deleting scopes.
If a scope with a value owner address is being updated, and the ONLY change is to that value owner address, then ONLY these signer requirements are applied and all other signer requirements are ignored. If the value owner address is not changing, these requirements do not apply. If the value owner address is changing as well as one or more other fields, these requirements apply as well as the other signer requirements.
  • When a value owner address is being set to a marker, at least one of the signers must have deposit permission on that marker.
  • When a value owner address is a marker and is being changed, at least one of the signers must have withdraw permission on that marker.
  • When a value owner address is a non-marker address, and is being changed, that existing address must be one of the signers.
  • When a value owner address is empty, and is being changed, standard scope signer requirements are also applied even if that's the only change to the scope.

Smart Contract Requirements

The following are requirements related to smart contract usage of the x/metadata module:
  • A party with a smart contract address MUST have the PROVENANCE role.
  • A party with the PROVENANCE role MUST have the address of a smart contract.
  • When a smart contract signs a message, it MUST be first or have only smart-contract signers before it, and SHOULD include the invoker address(es) after.
  • When a smart contract is a signer, it must either be a party/owner, or have authorizations (via x/authz) from all signers after it.
  • If a smart contract is a signer, but not a party, it cannot be the only signer, and cannot be the last signer.

With Party Rollup Required

When a scope has require_party_rollup = true, all session parties must also be listed in the scope owners.
The use of optional = true parties is also allowed.
The party types (aka roles) defined in specifications, in conjunction with they entry's parties dictate the signers that are required (in addition to any optional = false parties).
For example, if a scope has an optional = false CONTROLLER (address A), and two optional = true SERVICERs (addresses B, and C), and a session is being written using a contract spec that requires just a SERVICER signature, then to write that session, either address B or C must be a signer (due to the contract spec), and A must also sign (because they're optional = false in the scope).

Writing or Deleting a Scope With Party Rollup

  • All roles required by the scope spec must have a party in the owners.
  • If not new:
    • All optional = false existing owners must be signers.
    • All roles required by the scope spec must have a signer and associated party from the existing scope.
  • Scope value owner address requirements are applied.

Writing a Session With Party Rollup

  • All proposed session parties must be present in this scope's owners.
  • All optional = false scope owners must be signers.
  • If new:
    • All roles required by the contract spec must have a signer and associated party in the proposed session.
  • If not new:
    • All roles required by the contract spec must have a signer and associated party in the existing session.
    • All roles required by the contract spec must have parties in the proposed session.
    • All optional = false existing parties must also be signers.

Writing a Record With Party Rollup

  • All roles required by the record spec must have a signer and associated party in the session.
  • All optional = false scope owners and session parties must be signers.
  • If the record is changing sessions, all optional = false previous session parties must be signers.

Deleting a Record With Party Rollup

  • All roles required by the record spec must have a signer and associated party in the scope.
  • All optional = false scope owners must be signers.

Without Party Rollup Required

When a scope has require_party_rollup = false, then optional = true parties are not allowed in the scope or any of its sessions.

Writing or Deleting a Scope Without Party Rollup

  • All roles required by the scope spec must have a party in the owners.
  • If not new, all existing owners must sign.
  • Scope value owner address requirements are applied.

Writing a Session Without Party Rollup

  • All roles required by the contract spec must have a party in the session parties.
  • All scope owners must sign.

Writing a Record Without Party Rollup

  • All roles required by the record spec must have a party in the session parties.
  • All session parties must sign.
  • If the record is changing to a new session, all previous session parties must sign.

Deleting a Record Without Party Rollup

  • All scope owners must sign.

State

Summary

The Metadata module manages state for three categories of off-chain information: entries (scopes, sessions, records) that group and identify data with unique metadata addresses using specific byte array structures, specifications (scope, contract, record) that define validation parameters and party requirements, and object store locators that indicate off-chain data locations, with comprehensive indexing systems for efficient data association and retrieval.

The Metadata module manages the state of several types of entries related to off-chain information.

Entries

The term "entries" refers to scopes, sessions, and records. They group and identify information.

Scopes

A scope is a high-level grouping of information combined with some access control.
  • A scope must conform to a pre-determined scope specification.
  • A scope is used to group together many sessions and records.

Scope Keys (Metadata Addresses)

Byte Array Length: 17
Byte range
Description
0
0x00
1-16
UUID of this scope.
  • Field Name: Scope.scope_id
  • Bech32 HRP: "scope"
  • Bech32 Example: "scope1qzge0zaztu65tx5x5llv5xc9ztsqxlkwel"

Scope Values

protobuf
// Scope defines a root reference for a collection of records owned by one or more parties. message Scope { option (gogoproto.goproto_stringer) = false; // Unique ID for this scope. Implements sdk.Address interface for use where addresses are required in Cosmos bytes scope_id = 1 [(gogoproto.nullable) = false, (gogoproto.customtype) = "MetadataAddress"]; // the scope specification that contains the specifications for data elements allowed within this scope bytes specification_id = 2 [(gogoproto.nullable) = false, (gogoproto.customtype) = "MetadataAddress"]; // These parties represent top level owners of the records within. These parties must sign any requests that modify // the data within the scope. These addresses are in union with parties listed on the sessions. repeated Party owners = 3 [(gogoproto.nullable) = false]; // Addresses in this list are authorized to receive off-chain data associated with this scope. repeated string data_access = 4; // An address that controls the value associated with this scope. Standard blockchain accounts and marker accounts // are supported for this value. This attribute may only be changed by the entity indicated once it is set. string value_owner_address = 5; // Whether all parties in this scope and its sessions must be present in this scope's owners field. // This also enables use of optional=true scope owners and session parties. bool require_party_rollup = 6; }

Scope Indexes

Scopes by owner:
  • Type byte: 0x17
  • Part 1: The owner address (length byte then value bytes)
  • Part 2: All bytes of the scope key
Scopes by Scope Specification:
  • Type byte: 0x11
  • Part 1: All bytes of the scope specification key
  • Part 2: All bytes of the scope key
Scopes by value owner:
  • Type byte: 0x18
  • Part 1: The value owner address (length byte then value bytes)
  • Part 2: All bytes of the scope key

Sessions

A session is a grouping of records and the parties in charge of those records.
  • A session must conform to a pre-determined contract specification.
  • A session groups together a collection of records.
  • A session is part of exactly one scope.

Session Keys (Metadata Addresses)

Byte Array Length: 33
Byte range
Description
0
0x01
1-16
UUID of the scope that this session is part of
17-32
UUID of this session
  • Field Name: Session.session_id
  • Bech32 HRP: "session"
  • Bech32 Example: "session1qxge0zaztu65tx5x5llv5xc9zts9sqlch3sxwn44j50jzgt8rshvqyfrjcr"

Session Values

protobuf
// Session defines an execution context against a specific specification instance. // The context will have a specification and set of parties involved. // // NOTE: When there are no more Records within a Scope that reference a Session, the Session is removed. message Session { option (gogoproto.goproto_stringer) = false; bytes session_id = 1 [(gogoproto.nullable) = false, (gogoproto.customtype) = "MetadataAddress"]; // unique id of the contract specification that was used to create this session. bytes specification_id = 2 [(gogoproto.nullable) = false, (gogoproto.customtype) = "MetadataAddress"]; // parties is the set of identities that signed this contract repeated Party parties = 3 [(gogoproto.nullable) = false]; // name to associate with this session execution context, typically classname string name = 4; // context is a field for storing client specific data associated with a session. bytes context = 5; // Created by, updated by, timestamps, version number, and related info. AuditFields audit = 99; }

Session Indexes

There are no extra indexes involving sessions. Note, though, that the session key is constructed in a way that automatically indexes sessions by scope.

Records

A record identifies the inputs and outputs of a process. It is conceptually similar to the values involved in a method call.
  • A record must conform to a pre-determined record specification.
  • A record is part of exactly one scope.
  • A record is part of exactly one session.

Record Keys (Metadata Addresses)

Byte Array Length: 33
Byte range
Description
0
0x02
1-16
UUID of the scope that this record is part of
17-32
First 16 bytes of the SHA256 checksum of this record's name
  • Field Name: Record.record_id
  • Bech32 HRP: "record"
  • Bech32 Example: "record1q2ge0zaztu65tx5x5llv5xc9ztsw42dq2jdvmdazuwzcaddhh8gmu3mcze3"

Record Values

protobuf
// A record (of fact) is attached to a session or each consideration output from a contract message Record { option (gogoproto.goproto_stringer) = false; // name/identifier for this record. Value must be unique within the scope. Also known as a Fact name string name = 1; // id of the session context that was used to create this record (use with filtered kvprefix iterator) bytes session_id = 2 [(gogoproto.nullable) = false, (gogoproto.customtype) = "MetadataAddress"]; // process contain information used to uniquely identify an execution on or off chain that generated this record Process process = 3 [(gogoproto.nullable) = false]; // inputs used with the process to achieve the output on this record repeated RecordInput inputs = 4 [(gogoproto.nullable) = false]; // output(s) is the results of executing the process on the given process indicated in this record repeated RecordOutput outputs = 5 [(gogoproto.nullable) = false]; // specification_id is the id of the record specification that was used to create this record. bytes specification_id = 6 [(gogoproto.nullable) = false, (gogoproto.customtype) = "MetadataAddress"]; }

Record Indexes

There are no extra indexes involving records. Note, though, that the record key is constructed in a way that automatically indexes records by scope.

Specifications

The term "specifications" refers to scope specifications, contract specifications, and record specifications. They define validation parameters for the various entries. Ideally, specifications will be used for multiple entries.

Scope Specifications

A scope specification defines validation parameters for scopes. They group together contract specifications and define roles that must be involved in a scope.

Scope Specification Keys (Metadata Addresses)

Byte Array Length: 17
Byte range
Description
0
0x04
1-16
UUID of this scope specification
  • Field Name: ScopeSpecification.specification_id
  • Bech32 HRP: "scopespec"
  • Bech32 Example: "scopespec1qnwg86nsatx5pl56muw0v9ytlz3qu3jx6m"

Scope Specification Values

protobuf
// ScopeSpecification defines the required parties, resources, conditions, and consideration outputs for a contract message ScopeSpecification { option (gogoproto.goproto_stringer) = false; // unique identifier for this specification on chain bytes specification_id = 1 [(gogoproto.nullable) = false, (gogoproto.customtype) = "MetadataAddress"]; // General information about this scope specification. Description description = 2; // Addresses of the owners of this scope specification. repeated string owner_addresses = 3; // A list of parties that must be present on a scope (and their associated roles) repeated PartyType parties_involved = 4; // A list of contract specification ids allowed for a scope based on this specification. repeated bytes contract_spec_ids = 5 [(gogoproto.nullable) = false, (gogoproto.customtype) = "MetadataAddress"]; }

Scope Specification Indexes

Scope specifications by owner:
  • Type byte: 0x19
  • Part 1: The owner address (length byte then value bytes)
  • Part 2: All bytes of the scope specification key
Scope Specifications by contract specification:
  • Type byte: 0x14
  • Part 1: All bytes of the contract specification key
  • Part 2: All bytes of the scope specification key
Scopes by Scope Specification:
  • Type byte: 0x11
  • Part 1: All bytes of the scope specification key
  • Part 2: All bytes of the scope key

Contract Specifications

A contract specification defines validation parameters for sessions. They contain source information and roles that must be involved in a session. They also group together record specifications.
A contract specification can be part of multiple scope specifications.

Contract Specification Keys (Metadata Addresses)

Byte Array Length: 17
Byte range
Description
0
0x03
1-16
UUID of this contract specification
  • Field Name: ContractSpecification.specification_id
  • Bech32 HRP: "contractspec"
  • Bech32 Example: "contractspec1q000d0q2e8w5say53afqdesxp2zqzkr4fn"

Contract Specification Values

protobuf
// ContractSpecification defines the required parties, resources, conditions, and consideration outputs for a contract message ContractSpecification { option (gogoproto.goproto_stringer) = false; // unique identifier for this specification on chain bytes specification_id = 1 [(gogoproto.nullable) = false, (gogoproto.customtype) = "MetadataAddress"]; // Description information for this contract specification Description description = 2; // Address of the account that owns this specificaiton repeated string owner_addresses = 3; // a list of party roles that must be fullfilled when signing a transaction for this contract specification repeated PartyType parties_involved = 4; // Reference to a metadata record with a hash and type information for the instance of code that will process this // contract oneof source { // the address of a record on chain that represents this contract bytes resource_id = 5 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"]; // the hash of contract binary (off-chain instance) string hash = 6; } // name of the class/type of this contract executable string class_name = 7; }

Contract Specification Indexes

Contract specifications by owner:
  • Type byte: 0x20
  • Part 1: The owner address (length byte then value bytes)
  • Part 2: All bytes of the contract specification key
Scope Specifications by contract specification:
  • Type byte: 0x14
  • Part 1: All bytes of the contract specification key
  • Part 2: All bytes of the scope specification key

Record Specifications

A record specification defines validation parameters for records. They contain expected inputs and outputs and parties that must be involved in a record.
A record specification is part of exactly one contract specification.

Record Specification Keys (Metadata Addresses)

Byte Array Length: 33
Byte range
Description
0
0x05
1-16
UUID of the contract specification that this record specification is part of
17-32
First 16 bytes of the SHA256 checksum of this record specification's name
  • Field Name: RecordSpecification.specification_id
  • Bech32 HRP: "recspec"
  • Bech32 Example: "recspec1qh00d0q2e8w5say53afqdesxp2zw42dq2jdvmdazuwzcaddhh8gmuqhez44"

Record Specification Values

protobuf
// RecordSpecification defines the specification for a Record including allowed/required inputs/outputs message RecordSpecification { option (gogoproto.goproto_stringer) = false; // unique identifier for this specification on chain bytes specification_id = 1 [(gogoproto.nullable) = false, (gogoproto.customtype) = "MetadataAddress"]; // Name of Record that will be created when this specification is used string name = 2; // A set of inputs that must be satisified to apply this RecordSpecification and create a Record repeated InputSpecification inputs = 3; // A type name for data associated with this record (typically a class or proto name) string type_name = 4; // Type of result for this record specification (must be RECORD or RECORD_LIST) DefinitionType result_type = 5; // Type of party responsible for this record repeated PartyType responsible_parties = 6; }

Record Specification Indexes

There are no extra indexes involving record specifications. Note, though, that the record key is constructed in a way that automatically indexes record specifications by contract specification.

Object Store Locators

An object store locator indicates the location of off-chain data.

Object Store Locator Keys

Byte Array Length: 21
Byte range
Description
0
0x21
1
Owner address length, either 0x14 (20) or 0x20 (32)
2-(21 or 33)
The bytes of the owner address.

Object Store Locator Values

protobuf
// Defines an Locator object stored on chain, which represents a owner( blockchain address) associated with a endpoint // uri for it's associated object store. message ObjectStoreLocator { option (cosmos.msg.v1.signer) = "owner"; // account address the endpoint is owned by string owner = 1; // locator endpoint uri string locator_uri = 2; // owners encryption key address string encryption_key = 3; }

Object Store Locator Indexes

There are no extra indexes involving object store locators.

Messages

Summary

The metadata module provides comprehensive message endpoints for managing off-chain data references through entries (scopes, sessions, records), specifications (scope, contract, record), object store locators, and account data, with detailed validation requirements, permission controls, and UUID-based identification systems for creating, updating, and deleting metadata structures within the Provenance blockchain ecosystem.

In this section we describe the processing of the metadata messages and the corresponding updates to the state. All created/modified state objects specified by each message are defined within the state section.
These endpoints, requests, and responses are defined in tx.proto.

Entries

Msg/WriteScope

A scope is created or updated using the WriteScope service method. Scopes are identified using their scope_id.

Request

protobuf
message MsgWriteScopeRequest { Scope scope = 1; repeated string signers = 2; string scope_uuid = 3; string spec_uuid = 4; }
The scope_uuid field is optional. It should be a uuid formated as a string using the standard UUID format. If supplied, it will be used to generate the appropriate scope id for use in the scope.scope_id field.
The spec_uuid field is optional. It should be a uuid formated as a string using the standard UUID format. If supplied, it will be used to generate the appropriate scope specification id for use in the scope.specification_id field.

Response

protobuf
message MsgWriteScopeResponse { MetadataAddress scope_id_info = 1; }

Expected failures

This service message is expected to fail if:
  • The scope_id is missing or invalid.
  • The specification_id is missing or invalid.
  • The owners list is empty.
  • Any of the owner address values aren't bech32 address strings.
  • Any of the data_access values aren't bech32 address strings.
  • A value_owner_address is provided that isn't a bech32 address string.
  • The signers do not have permission to write the scope.

Msg/DeleteScope

A scope is deleted using the DeleteScope service method.

Request

protobuf
message MsgDeleteScopeRequest { bytes scope_id = 1; repeated string signers = 2; }

Response

protobuf
message MsgDeleteScopeResponse {}

Expected failures

This service message is expected to fail if:
  • No scope exists with the given scope_id.
  • The signers do not have permission to delete the scope.

Msg/AddScopeDataAccess

Addresses can be added to a scope's data access list using the AddScopeDataAccess service method.

Request

protobuf
message MsgAddScopeDataAccessRequest { bytes scope_id = 1; repeated string data_access = 2; repeated string signers = 3; }

Response

protobuf
message MsgAddScopeDataAccessResponse {}

Expected failures

This service message is expected to fail if:
  • Any provided address is invalid.
  • Any provided address is already in the scope's data access list.
  • The signers do not have permission to update the scope.

Msg/DeleteScopeDataAccess

Addresses can be deleted from a scope's data access list using the DeleteScopeDataAccess service method.

Request

protobuf
message MsgDeleteScopeDataAccessRequest { bytes scope_id = 1; repeated string data_access = 2; repeated string signers = 3; }

Response

protobuf
message MsgDeleteScopeDataAccessResponse {}

Expected failures

This service message is expected to fail if:
  • Any provided address is not already in the scope's data access list.
  • The signers do not have permission to update the scope.

Msg/AddScopeOwner

Scope owners can be added to a scope using the AddScopeOwner service method.

Request

protobuf
message MsgAddScopeOwnerRequest { bytes scope_id = 1; repeated Party owners = 2; repeated string signers = 3; }

Response

protobuf
message MsgAddScopeOwnerResponse {}

Expected failures

This service message is expected to fail if:
  • Any new party is invalid.
  • An optional = true party is being added to a require_party_rollup = false scope.
  • The signers do not have permission to update the scope.

Msg/DeleteScopeOwner

Scope owners can be deleted from a scope using the DeleteScopeOwner service method. All owner parties with any of the provided addresses will be removed from the scope.

Request

protobuf
message MsgDeleteScopeOwnerRequest { bytes scope_id = 1; repeated string owners = 2; repeated string signers = 3; }

Response

protobuf
message MsgDeleteScopeOwnerResponse {}

Expected failures

This service message is expected to fail if:
  • Any provided owners (addresses) are not an address in a party in the scope.
  • The resulting scope owners do not meet scope specification requirements.
  • The signers do not have permission to update the scope.

Msg/UpdateValueOwners

The value owner address of one or more scopes can be updated using the UpdateValueOwners service method.

Request

protobuf
message MsgUpdateValueOwnersRequest { repeated bytes scope_ids = 1; string value_owner_address = 2; repeated string signers = 3; }

Response

protobuf
message MsgUpdateValueOwnersResponse {}

Expected failures

This service message is expected to fail if:
  • The new value owner address is invalid.
  • Any of the provided scope ids are not metadata scope identifiers or do not exist.
  • The signers are not allowed to update the value owner address of a provided scope.

Msg/MigrateValueOwner

All scopes with a given existing value owner address can be updated to have a new proposed value owner address using the MigrateValueOwner endpoint.

Request

protobuf
message MsgMigrateValueOwnerRequest { string existing = 1; string proposed = 2; repeated string signers = 3; }

Response

protobuf
message MsgMigrateValueOwnerResponse {}

Expected failures

This service message is expected to fail if:
  • Either the existing or proposed values are not valid bech32 addresses.
  • The existing address is not a value owner on any scopes.
  • The signers are not allowed to update the value owner address of a scope being updated.

Msg/WriteSession

A session is created or updated using the WriteSession service method. Sessions are identified using their session_id.

Request

protobuf
message MsgWriteSessionRequest { Session session = 1; repeated string signers = 2; SessionIdComponents session_id_components = 3; string spec_uuid = 4; }
The session_id_components field is optional. If supplied, it will be used to generate the appropriate session id for use in the session.session_id field.
The spec_uuid field is optional. It should be a uuid formated as a string using the standard UUID format. If supplied, it will be used to generate the appropriate contract specification id for use in the session.specification_id field.

Response

protobuf
message MsgWriteSessionResponse { MetadataAddress session_id_info = 1; }

Expected failures

This service message is expected to fail if multiple validation conditions are not met, including invalid session_id, specification_id, parties requirements, audit message length, and permission checks.

Msg/WriteRecord

A record is created or updated using the WriteRecord service method. Records are identified using their name and session_id.

Request

protobuf
message MsgWriteRecordRequest { Record record = 1; repeated string signers = 2; SessionIdComponents session_id_components = 3; string contract_spec_uuid = 4; }

Response

protobuf
message MsgWriteRecordResponse { MetadataAddress record_id_info = 1; }

Msg/DeleteRecord

A record is deleted using the DeleteRecord service method.

Request

protobuf
message MsgDeleteRecordRequest { bytes record_id = 1; repeated string signers = 2; }

Response

protobuf
message MsgDeleteRecordResponse {}

Expected failures

This service message is expected to fail if:
  • No record exists with the given record_id.
  • The signers do not have permission to delete the record.

Specifications

Msg/WriteScopeSpecification

A scope specification is created or updated using the WriteScopeSpecification service method. Scope specifications are identified using their specification_id.

Request

protobuf
message MsgWriteScopeSpecificationRequest { ScopeSpecification specification = 1; repeated string signers = 2; string spec_uuid = 3; }

Response

protobuf
message MsgWriteScopeSpecificationResponse { MetadataAddress scope_spec_id_info = 1; }

Msg/DeleteScopeSpecification

A scope specification is deleted using the DeleteScopeSpecification service method.

Request

protobuf
message MsgDeleteScopeSpecificationRequest { bytes specification_id = 1; repeated string signers = 2; }

Response

protobuf
message MsgDeleteScopeSpecificationResponse {}

Msg/WriteContractSpecification

A contract specification is created or updated using the WriteContractSpecification service method. Contract specifications are identified using their specification_id.

Request

protobuf
message MsgWriteContractSpecificationRequest { ContractSpecification specification = 1; repeated string signers = 2; string spec_uuid = 3; }

Response

protobuf
message MsgWriteContractSpecificationResponse { MetadataAddress contract_spec_id_info = 1; }

Msg/DeleteContractSpecification

A contract specification is deleted using the DeleteContractSpecification service method. This will also delete all record specifications associated with this contract specification.

Request

protobuf
message MsgDeleteContractSpecificationRequest { bytes specification_id = 1; repeated string signers = 2; }

Response

protobuf
message MsgDeleteContractSpecificationResponse {}

Msg/AddContractSpecToScopeSpec

A contract specification can be added to a scope specification using the AddContractSpecToScopeSpec service method.

Request

protobuf
message MsgAddContractSpecToScopeSpecRequest { bytes contract_specification_id = 1; bytes scope_specification_id = 2; repeated string signers = 3; }

Response

protobuf
message MsgAddContractSpecToScopeSpecResponse {}

Msg/DeleteContractSpecFromScopeSpec

A contract specification can be removed from a scope specification using the DeleteContractSpecFromScopeSpec service method.

Request

protobuf
message MsgDeleteContractSpecFromScopeSpecRequest { bytes contract_specification_id = 1; bytes scope_specification_id = 2; repeated string signers = 3; }

Response

protobuf
message MsgDeleteContractSpecFromScopeSpecResponse {}

Msg/WriteRecordSpecification

A record specification is created or updated using the WriteRecordSpecification service method. Record specifications are identified using their specification_id.

Request

protobuf
message MsgWriteRecordSpecificationRequest { RecordSpecification specification = 1; repeated string signers = 2; string contract_spec_uuid = 3; }

Response

protobuf
message MsgWriteRecordSpecificationResponse { MetadataAddress record_spec_id_info = 1; }

Msg/DeleteRecordSpecification

A record specification is deleted using the DeleteRecordSpecification service method.

Request

protobuf
message MsgDeleteRecordSpecificationRequest { bytes specification_id = 1; repeated string signers = 2; }

Response

protobuf
message MsgDeleteRecordSpecificationResponse {}

Object Store Locators

Msg/BindOSLocator

An Object Store Locator entry is created using the BindOSLocator service method.

Request

protobuf
message MsgBindOSLocatorRequest { ObjectStoreLocator locator = 1; }

Response

protobuf
message MsgBindOSLocatorResponse { ObjectStoreLocator locator = 1; }

Msg/DeleteOSLocator

An Object Store Locator entry is deleted using the DeleteOSLocator service method.

Request

protobuf
message MsgDeleteOSLocatorRequest { ObjectStoreLocator locator = 1; }

Response

protobuf
message MsgDeleteOSLocatorResponse { ObjectStoreLocator locator = 1; }

Msg/ModifyOSLocator

An Object Store Locator entry is updated using the ModifyOSLocator service method. Object Store Locators are identified by their owner.

Request

protobuf
message MsgModifyOSLocatorRequest { ObjectStoreLocator locator = 1; }

Response

protobuf
message MsgModifyOSLocatorResponse { ObjectStoreLocator locator = 1; }

Account Data

Msg/SetAccountData

Simple data (a string) can be associated with scopes using the SetAccountData service method.
protobuf
message MsgSetAccountDataRequest { string metadata_addr = 1; string value = 2; string signer = 3; }
protobuf
message MsgSetAccountDataResponse {}
This service message is expected to fail if:
  • The provided address is not a scope id.
  • The provided scope id does not exist.
  • The signers do not have authority to update the entry.
  • The provided value is too long (as defined by the attribute module params).

Authz Grants

Authz requires the use of fully qualified message type URLs when applying grants to an address. See 04_authz.md for more details.
Fully qualified metadata message type URLs:
  • /provenance.metadata.v1.MsgWriteScopeRequest
  • /provenance.metadata.v1.MsgDeleteScopeRequest
  • /provenance.metadata.v1.MsgAddScopeDataAccessRequest
  • /provenance.metadata.v1.MsgDeleteScopeDataAccessRequest
  • /provenance.metadata.v1.MsgAddScopeOwnerRequest
  • /provenance.metadata.v1.MsgDeleteScopeOwnerRequest
  • /provenance.metadata.v1.MsgUpdateValueOwnersRequest
  • /provenance.metadata.v1.MsgMigrateValueOwnerRequest
  • /provenance.metadata.v1.MsgWriteSessionRequest
  • /provenance.metadata.v1.MsgWriteRecordRequest
  • /provenance.metadata.v1.MsgDeleteRecordRequest
  • /provenance.metadata.v1.MsgWriteScopeSpecificationRequest
  • /provenance.metadata.v1.MsgDeleteScopeSpecificationRequest
  • /provenance.metadata.v1.MsgWriteContractSpecificationRequest
  • /provenance.metadata.v1.MsgDeleteContractSpecificationRequest
  • /provenance.metadata.v1.MsgAddContractSpecToScopeSpecRequest
  • /provenance.metadata.v1.MsgDeleteContractSpecFromScopeSpecRequest
  • /provenance.metadata.v1.MsgWriteRecordSpecificationRequest
  • /provenance.metadata.v1.MsgDeleteRecordSpecificationRequest
  • /provenance.metadata.v1.MsgBindOSLocatorRequest
  • /provenance.metadata.v1.MsgDeleteOSLocatorRequest
  • /provenance.metadata.v1.MsgModifyOSLocatorRequest
  • /provenance.metadata.v1.MsgSetAccountDataRequest

Events

Summary

The metadata module emits comprehensive events for all metadata operations including a generic transaction completion event with module endpoint and signer information, plus specific create/update/delete events for each metadata type (scopes, sessions, records, scope specifications, contract specifications, record specifications, and object store locators) with relevant bech32 address identifiers for complete audit trails and monitoring capabilities.

The metadata module emits the following events and telemetry information.

Generic

EventTxCompleted

This event is emitted whenever a TX has completed without issues. It will usually be accompanied by one or more of the other events.
Attribute Key
Attribute Value
Module
"metadata"
Endpoint
The name of the rpc called, e.g. "WriteScope"
Signers
List of bech32 address strings of the msg signers

Scope

EventScopeCreated

This event is emitted whenever a new scope is written.
Attribute Key
Attribute Value
ScopeAddr
The bech32 address string of the ScopeId

EventScopeUpdated

This event is emitted whenever an existing scope is updated.
Attribute Key
Attribute Value
ScopeAddr
The bech32 address string of the ScopeId

EventScopeDeleted

This event is emitted whenever an existing scope is deleted.
Attribute Key
Attribute Value
ScopeAddr
The bech32 address string of the ScopeId

Session

EventSessionCreated

This event is emitted whenever a new session is written.
Attribute Key
Attribute Value
SessionAddr
The bech32 address string of the SessionId
ScopeAddr
The bech32 address string of the session's ScopeId

EventSessionUpdated

This event is emitted whenever an existing session is updated.
Attribute Key
Attribute Value
SessionAddr
The bech32 address string of the SessionId
ScopeAddr
The bech32 address string of the session's ScopeId

EventSessionDeleted

This event is emitted whenever an existing session is deleted.
Attribute Key
Attribute Value
SessionAddr
The bech32 address string of the SessionId
ScopeAddr
The bech32 address string of the session's ScopeId

Record

EventRecordCreated

This event is emitted whenever a new record is written.
Attribute Key
Attribute Value
RecordAddr
The bech32 address string of the RecordId
SessionAddr
The bech32 address string of the record's SessionId
ScopeAddr
The bech32 address string of the record's ScopeId

EventRecordUpdated

This event is emitted whenever an existing record is updated.
Attribute Key
Attribute Value
RecordAddr
The bech32 address string of the RecordId
SessionAddr
The bech32 address string of the record's SessionId
ScopeAddr
The bech32 address string of the record's ScopeId

EventRecordDeleted

This event is emitted whenever an existing record is deleted.
Attribute Key
Attribute Value
RecordAddr
The bech32 address string of the RecordId
ScopeAddr
The bech32 address string of the record's ScopeId

Scope Specification

EventScopeSpecificationCreated

This event is emitted whenever a new scope specification is written.
Attribute Key
Attribute Value
ScopeSpecificationAddr
The bech32 address string of the SpecificationId

EventScopeSpecificationUpdated

This event is emitted whenever an existing scope specification is updated.
Attribute Key
Attribute Value
ScopeSpecificationAddr
The bech32 address string of the SpecificationId

EventScopeSpecificationDeleted

This event is emitted whenever an existing scope specification is deleted.
Attribute Key
Attribute Value
ScopeSpecificationAddr
The bech32 address string of the SpecificationId

Contract Specification

EventContractSpecificationCreated

This event is emitted whenever a new contract specification is written.
Attribute Key
Attribute Value
ContractSpecificationAddr
The bech32 address string of the SpecificationId

EventContractSpecificationUpdated

This event is emitted whenever an existing contract specification is updated.
Attribute Key
Attribute Value
ContractSpecificationAddr
The bech32 address string of the SpecificationId

EventContractSpecificationDeleted

This event is emitted whenever an existing contract specification is deleted.
Attribute Key
Attribute Value
ContractSpecificationAddr
The bech32 address string of the SpecificationId

Record Specification

EventRecordSpecificationCreated

This event is emitted whenever a new record specification is written.
Attribute Key
Attribute Value
RecordSpecificationAddr
The bech32 address string of the SpecificationId
ContractSpecificationAddr
The bech32 address string of the Contract SpecificationId

EventRecordSpecificationUpdated

This event is emitted whenever an existing record specification is updated.
Attribute Key
Attribute Value
RecordSpecificationAddr
The bech32 address string of the SpecificationId
ContractSpecificationAddr
The bech32 address string of the Contract SpecificationId

EventRecordSpecificationDeleted

This event is emitted whenever an existing record specification is deleted.
Attribute Key
Attribute Value
RecordSpecificationAddr
The bech32 address string of the SpecificationId
ContractSpecificationAddr
The bech32 address string of the Contract SpecificationId

Object Store Locator

EventOSLocatorCreated

This event is emitted whenever a new object store locator is written.
Attribute Key
Attribute Value
Owner
The bech32 address string of the Owner

EventOSLocatorUpdated

This event is emitted whenever an existing object store locator is updated.
Attribute Key
Attribute Value
Owner
The bech32 address string of the Owner

EventOSLocatorDeleted

This event is emitted whenever an existing object store locator is deleted.
Attribute Key
Attribute Value
Owner
The bech32 address string of the Owner

Queries

The Provenance Blockchain metadata module provides a comprehensive query service for accessing and retrieving metadata information stored on the blockchain. The query service includes endpoints for accessing primary data (scopes, sessions, records), specifications (scope specs, contract specs, record specs), object store locators, and account data, enabling developers to efficiently query and manage off-chain data references and their associated metadata structures.

Primary Data Queries

Params

Queries the parameters of the x/metadata module.
HTTP Endpoint: GET /provenance/metadata/v1/params
Request: QueryParamsRequestResponse: QueryParamsResponse

Scope

Searches for a scope by ID, session address, or record address.
HTTP Endpoints:
  • GET /provenance/metadata/v1/scope/{scope_id}
  • GET /provenance/metadata/v1/session/{session_addr}/scope
  • GET /provenance/metadata/v1/record/{record_addr}/scope
Request: ScopeRequestResponse: ScopeResponse
The scope_id can be either a scope UUID (e.g. 91978ba2-5f35-459a-86a7-feca1b0512e0) or a scope address (e.g. scope1qzge0zaztu65tx5x5llv5xc9ztsqxlkwel).

ScopesAll

Retrieves all scopes with optional pagination.
HTTP Endpoint: GET /provenance/metadata/v1/scopes/all
Request: ScopesAllRequestResponse: ScopesAllResponse

Sessions

Searches for sessions by scope ID, session ID, record address, or record name.
HTTP Endpoints:
  • GET /provenance/metadata/v1/session/{session_id}
  • GET /provenance/metadata/v1/scope/{scope_id}/sessions
  • GET /provenance/metadata/v1/scope/{scope_id}/session/{session_id}
  • GET /provenance/metadata/v1/record/{record_addr}/session
  • GET /provenance/metadata/v1/scope/{scope_id}/record/{record_name}/session
Request: SessionsRequestResponse: SessionsResponse

SessionsAll

Retrieves all sessions with optional pagination.
HTTP Endpoint: GET /provenance/metadata/v1/sessions/all
Request: SessionsAllRequestResponse: SessionsAllResponse

Records

Searches for records by record address, scope ID, session ID, or name.
HTTP Endpoints:
  • GET /provenance/metadata/v1/record/{record_addr}
  • GET /provenance/metadata/v1/scope/{scope_id}/records
  • GET /provenance/metadata/v1/scope/{scope_id}/record/{name}
  • GET /provenance/metadata/v1/scope/{scope_id}/session/{session_id}/records
  • GET /provenance/metadata/v1/scope/{scope_id}/session/{session_id}/record/{name}
  • GET /provenance/metadata/v1/session/{session_id}/records
  • GET /provenance/metadata/v1/session/{session_id}/record/{name}
Request: RecordsRequestResponse: RecordsResponse

RecordsAll

Retrieves all records with optional pagination.
HTTP Endpoint: GET /provenance/metadata/v1/records/all
Request: RecordsAllRequestResponse: RecordsAllResponse

Ownership

Returns scope identifiers that list the given address as either a data or value owner.
HTTP Endpoint: GET /provenance/metadata/v1/ownership/{address}
Request: OwnershipRequestResponse: OwnershipResponse

ValueOwnership

Returns scope identifiers that list the given address as the value owner.
HTTP Endpoint: GET /provenance/metadata/v1/valueownership/{address}
Request: ValueOwnershipRequestResponse: ValueOwnershipResponse

Specification Queries

ScopeSpecification

Returns a scope specification for the given specification ID.
HTTP Endpoint: GET /provenance/metadata/v1/scopespec/{specification_id}
Request: ScopeSpecificationRequestResponse: ScopeSpecificationResponse
The specification_id can be either a UUID (e.g. dc83ea70-eacd-40fe-9adf-1cf6148bf8a2) or a bech32 scope specification address (e.g. scopespec1qnwg86nsatx5pl56muw0v9ytlz3qu3jx6m).

ScopeSpecificationsAll

Retrieves all scope specifications.
HTTP Endpoint: GET /provenance/metadata/v1/scopespecs/all
Request: ScopeSpecificationsAllRequestResponse: ScopeSpecificationsAllResponse

ContractSpecification

Returns a contract specification for the given specification ID.
HTTP Endpoint: GET /provenance/metadata/v1/contractspec/{specification_id}
Request: ContractSpecificationRequestResponse: ContractSpecificationResponse

ContractSpecificationsAll

Retrieves all contract specifications.
HTTP Endpoint: GET /provenance/metadata/v1/contractspecs/all
Request: ContractSpecificationsAllRequestResponse: ContractSpecificationsAllResponse

RecordSpecificationsForContractSpecification

Returns the record specifications for the given contract specification.
HTTP Endpoint: GET /provenance/metadata/v1/contractspec/{specification_id}/recordspecs
Request: RecordSpecificationsForContractSpecificationRequestResponse: RecordSpecificationsForContractSpecificationResponse

RecordSpecification

Returns a record specification for the given input.
HTTP Endpoints:
  • GET /provenance/metadata/v1/recordspec/{specification_id}
  • GET /provenance/metadata/v1/contractspec/{specification_id}/recordspec/{name}
Request: RecordSpecificationRequestResponse: RecordSpecificationResponse

RecordSpecificationsAll

Retrieves all record specifications.
HTTP Endpoint: GET /provenance/metadata/v1/recordspecs/all
Request: RecordSpecificationsAllRequestResponse: RecordSpecificationsAllResponse

GetByAddr

Retrieves metadata given any address(es).
HTTP Endpoint: GET /provenance/metadata/v1/addr/{addrs}
Request: GetByAddrRequestResponse: GetByAddrResponse

Object Store Locator Queries

OSLocatorParams

Returns all parameters for the object store locator sub module.
HTTP Endpoint: GET /provenance/metadata/v1/locator/params
Request: OSLocatorParamsRequestResponse: OSLocatorParamsResponse

OSLocator

Returns an ObjectStoreLocator by its owner's address.
HTTP Endpoint: GET /provenance/metadata/v1/locator/{owner}
Request: OSLocatorRequestResponse: OSLocatorResponse

OSLocatorsByURI

Returns all ObjectStoreLocator entries for a locator URI.
HTTP Endpoint: GET /provenance/metadata/v1/locator/uri/{uri}
Request: OSLocatorsByURIRequestResponse: OSLocatorsByURIResponse

OSLocatorsByScope

Returns all ObjectStoreLocator entries for all signers present in the specified scope.
HTTP Endpoint: GET /provenance/metadata/v1/locator/scope/{scope_id}
Request: OSLocatorsByScopeRequestResponse: OSLocatorsByScopeResponse

OSAllLocators

Returns all ObjectStoreLocator entries.
HTTP Endpoint: GET /provenance/metadata/v1/locators/all
Request: OSAllLocatorsRequestResponse: OSAllLocatorsResponse

Account Data Queries

AccountData

Gets the account data associated with a metadata address. Currently, only scope IDs are supported.
HTTP Endpoint: GET /provenance/metadata/v1/accountdata/{metadata_addr}
Request: AccountDataRequestResponse: AccountDataResponse

Related Resources

protobuf
// Example Query Service Definition // Source: https://github.com/provenance-io/provenance service Query { // Params queries the parameters of x/metadata module. rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { option (google.api.http).get = "/provenance/metadata/v1/params"; } // Scope searches for a scope. rpc Scope(ScopeRequest) returns (ScopeResponse) { option (google.api.http) = { get: "/provenance/metadata/v1/scope/{scope_id}" additional_bindings: {get: "/provenance/metadata/v1/session/{session_addr}/scope"} additional_bindings: {get: "/provenance/metadata/v1/record/{record_addr}/scope"} }; } }

Params

The Provenance Blockchain metadata module provides a system for referencing off-chain information and can be used to record and validate information as well as the processes that create the information. The metadata module consists of base module functionality and specialized sub-modules, each with their own configurable parameters that control various aspects of metadata handling and storage.

Base Module Parameters

The base metadata module itself does not have any parameters.

Object Store Locator Parameters

The object store locator sub-module contains the following parameters:
Key
Type
Example
MaxUriLength
uint32
2048

MaxUriLength

This parameter defines the maximum allowed length for URIs in the object store locator system. The default value is set to 2048 characters, which provides sufficient space for most URI structures while preventing excessively long URIs that could impact system performance.

Related Resources

protobuf
// Example from metadata asset model repository // Source: https://github.com/provenance-io/metadata-asset-model // Metadata address structure for scopes, sessions, and records message MetadataAddress { bytes scope_id = 1; bytes specification_id = 2; // Additional fields for metadata addressing }

Usage Context

The metadata parameters are essential for configuring how the Provenance Blockchain handles off-chain data references, ensuring proper validation and storage limits for metadata operations. These parameters work in conjunction with the broader metadata service architecture that manages scopes, sessions, and records on the blockchain.

Special Topics

TelemetryAuthZ
Share
Content