Grid Product Smart Contract Specification
Overview
Grid Product is a smart contact designed to run with the Sawtooth Sabre smart contract engine.
Grid Product is designed to supply Hyperledger Grid with a generic and extendable framework for storing product master data. A product in this case, is any item that is transacted, traded or referenced in a supply chain. Grid Product offers explicit support for products defined using the GS1, but is also designed to be flexible enough to support other standards.
Grid Product uses the Pike smart contract to manage permissions for creating, updating, and deleting products, as well as for managing the organizations that own each product, and uses the Schema smart contract to describe the requirements for the product entities.
State
All Grid Product object are serialized using Protocol Buffers before being
stored in state. These objects include Product, ProductList
, and
PropertyValue
.
Product
A product is an arbitrary list of properties that is uniquely identified by a
product_id
. The properties
are described by a schema that was previously
defined using the Schema smart contract. The schema that the product will be
checked against is dictated by the product’s product_namespace
field.
Currently, only the GS1
namespace has been defined.
A product has four fields
- product_id: A unique identifier for the product. For the GS1 namespace the product_id is a GS1 GTIN.
- product_namespace: The namespace that the product belongs to. A product’s
namespace dictates the rules for defining its
product_id
and the properties belonging to the product. Currently only the GS1 namespace is defined. - owner: The Pike organization ID of the organization that owns the product.
- properties: An arbitrary list of properties that describes the product. These properties are defined by a schema defined by the Schema smart contract.
message Product {
enum ProductNamespace {
UNSET_NAMESPACE = 0;
GS1 = 1;
}
ProductNamespace product_namespace = 1;
string product_id = 2;
string owner = 3;
repeated PropertyValue properties = 4;
}
Product List
Products whose addresses collide are stored in a product list. A product list contains only one field.
message ProductList {
repeated Product entries = 1;
}
Addressing for GS1 products
In order to uniquely locate GS1 products in the Merkle-Radix state system, an address must be constructed which identifies the storage location of the Product representation.
All Grid addresses are prefixed by the 6-hex-character namespace prefix “621dee”, Products are further prefixed under the Grid namespace with reserved enumerations of “02” (“00” and “01” being reserved for other purposes) indicating “Products” and an additional “01” indicating “GS1 Products”.
Therefore, all addresses starting with the following string are Grid products:
"621dee" + "02" + "01"
Grid GS1 Products are identified by a GTIN and are expected to contain a Product representation which conforms with the GS1 product schema.
GTIN formats consist of 14-digit “numeric strings” which include some amount of internal “0” padding depending on the specific GTIN format (GTIN-8, GTIN-12, GTIN-13, or GTIN-14). After the 10-hex-characters that are consumed by the grid namespace prefix, the product, and GS1 prefixes, there are 60 hex characters remaining in the address. The 14 digits of the GTIN can be left padded with 44-hex-character zeroes and right padded with 2-hex-character zeroes to accommodate potential future storage associated with the GS1 Product representation, for example:
"621dee" + "02" + "01" + "00000000000000000000000000000000000000000000" +
14-character "numeric string" product_id + "00" // product_id == GTIN
A full GS1 Product address using the example GTIN from https://www.gtin.info/ would therefore be:
"621dee0201000000000000000000000000000000000000000000000001234560001200"
Transaction Payload
Product Payload Transaction
ProductPayload
contains an action enum and the associated action payload. This
allows for the action payload to be dispatched to the appropriate logic.
Only the defined actions are available and only one action payload should be
defined in the ProductPayload
.
message ProductPayload {
enum Actions {
UNSET_ACTION = 0;
PRODUCT_CREATE = 1;
PRODUCT_UPDATE = 2;
PRODUCT_DELETE = 3;
}
Action action = 1;
// Approximately when transaction was submitted, as a Unix UTC timestamp
uint64 timestamp = 2;
ProductCreateAction product_create = 3;
ProductUpdateAction product_update = 4;
ProductDeleteAction product_delete = 5;
}
message ProductCreateAction {
enum Product_Namespace {
UNSET_NAMESPACE = 0;
GS1 = 1;
}
// product_namespace and product_id are used in deriving the state address
Product_Namespace product_namespace = 1;
string product_id = 2;
string owner = 3;
repeated PropertyValues properties = 4;
}
message ProductUpdateAction {
enum Product_Namespace {
UNSET_NAMESPACE = 0;
GS1 = 1;
}
// product_namespace and product_id are used in deriving the state address
Product_Namespace product_namespace = 1;
string product_id = 2;
// this will replace all properties currently defined
repeated PropertyValues properties = 4;
}
message ProductDeleteAction {
enum Product_Namespace {
UNSET_NAMESPACE = 0;
GS1 = 1;
}
// product_namespace and product_id are used in deriving the state address
Product_Namespace product_namespace = 1;
string product_id = 2;
}
Product Create Action
ProductCreateAction
adds a new product to state. The transaction should be
submitted by an agent, which is identified by its signing key, acting on behalf
of the organization that corresponds to the owner in the create transaction.
(Organizations and agents are defined by the Pike smart contract.)
Validation requirements:
- If a product with
product_id
already exists the transaction is invalid. - The signer of the transaction must be an agent in the Pike state and must belong to an organization in Pike state, otherwise the transaction is invalid.
- The agent must have the permission
can_create_product
for the organization, otherwise the transaction is invalid. - If the
product_namespace
is GS1, the organization must contain a GS1 Company Prefix in its metadata (gs1_company_prefixes
), and the prefix must match the company prefix in theproduct_id
, which is a GTIN if GS1, otherwise the transaction is invalid. - The properties must be valid for the
product_namespace
. For example, if the product is GS1 product, its properties must only contain properties that are included in the GS1 Schema. If it includes a property not in the GS1 Schema the transaction is invalid.
If all requirements are met, the transaction will be accepted, the batch will be written to a block, and the product will be created in state.
Product Update Action
ProductUpdateAction
updates an existing product in state. The transaction
should be submitted by an agent, identified by its signing key, acting on
behalf of an organization that corresponds to the owner in the product being
updated. (Organizations and agents are defined by the Pike smart contract.)
Validation requirements:
- If a product with
product_id
does not exist the transaction is invalid. - The signer of the transaction must be an agent in the Pike state and must belong to an organization in Pike state, otherwise the transaction is invalid.
- The owner in the product must match the organization that the agent belongs to, otherwise the transaction is invalid.
- The agent must have the permission
can_update_product
for the organization, otherwise the transaction is invalid. - The new properties must be valid for the
product_namespace
. For example, if the product is GS1 product, its properties must only contain properties that are included in the GS1 Schema. If it includes a property not in the GS1 Scheme the transaction is invalid.
The properties in the product will be swapped for the new properties and the updated product will be set in state.
Product Delete Action
ProductDeleteAction
removes an existing product from state. The transaction
should be submitted by an agent, identified by its signing key, acting on behalf
of the organization that corresponds to the org_id
in the product being updated.
(Organizations and agents are defined by the Pike smart contract.)
Validation requirements:
- If a product with
product_id
does not exist the transaction is invalid. - The signer of the transaction must be an agent in the Pike state and must belong to an organization in Pike state, otherwise the transaction is invalid.
- The owner in the product must match the organization that the agent belongs to, otherwise the transaction is invalid.
- The agent must have the permission
can_delete_product
for the organization otherwise the transaction is invalid.
Inputs and Outputs
Product Create Action
The inputs for ProductCreateAction
must include:
- Address of the Agent submitting the transaction
- Address of the Organization the Product is being created for
- Address of the Product Namespace Schema the product’s properties must match
- Address of the Product to be created
The outputs for ProductCreateAction
must include:
- Address of the Product created
Product Update Action
The inputs for ProductUpdateAction
must include:
- Address of the Agent submitting the transaction
- Address of the Organization the Product is being updated for
- Address of the Product Namespace Schema the product’s properties must match
- Address of the Product to be updated
The outputs for ProductUpdateAction
must include:
- Address of the Product updated
Product Delete Action
The inputs for ProductDeleteAction
must include:
- Address of the Agent submitting the transaction
- Address of the Organization the Product is being deleted for
- Address of the Product to be deleted
The outputs for ProductDeleteAction
must include:
- Address of the Product to be deleted