documents

package
v0.0.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 16, 2019 License: MIT Imports: 41 Imported by: 0

Documentation

Overview

Package documents implements Centrifuge document models.

Models

The idea of having a model is to make the business functions of the document clearer and more readable. This also enables proper types and validations on the fields that require them. When an API call is received, the following list of transformations/steps needs to be executed on the request object.

1. Model conversion: this would ensure that proper types are created for each of the fields of the input document plus handling basic level validations that does not require business level understanding of the document. eg: telephone numbers, IDs

2. The converted model is updated using the existing document. After this there would be two versions of the document in the system old and the new

3. The two versions of the document are passed through a purpose specific validator chain that implements the following interface. (see chapter on validation)

Model Storage

A model objects must support storage in DB as a JSON serialized object. The rationale behind this is that JSON format enables easier inter-operability between systems that would depend on database access such as BI (Although we do NOT recommend directly accessing the db eventually when we have proper APIs for accessing all data).

// example of an implementation
type InvoiceModel struct {
// all invoice fields with proper types here
}

func (i *InvoiceModel) PackCoreDocument() *coredocumentpb.CoreDocument {
panic("implement me")
}

func (i *InvoiceModel) UnpackCoreDocument(cd *coredocumentpb.CoreDocument) error {
panic("implement me")
}

func (i *InvoiceModel) JSON() ([]byte, error) {
panic("implement me")
}

func (i *InvoiceModel) Type() reflect.Type {
return reflect.TypeOf(i)
}

Model Package Hierarchy Specification

In the new package structure the package `documents` includes all model relevant implementations and interfaces. The actual implementation can be found at the package `invoice` or `purchaseorder`. The package `documents` should not include any of the actual implementations to avoid cycle dependencies.

Validation

Validations should be done depending on the situation. The below table is an example that shows a few examples of validations that should only depending on context of the validation.

|                           | Verify  SigningRoot | Verify DocumentRoot | Check Invoice State Transition | Node must be in collaborators |
|---------------------------|---------------------|---------------------|--------------------------------|-------------------------------|
| Client Submission         |                     |                     | yes                            | yes                           |
| Signature Request         | yes                 |                     |                                |                               |
| Receive Anchored Document | yes                 | yes                 |                                | yes                           |
| Store in DB               | yes                 | only if set         |                                | yes                           |

Validations are implemented in individual checks. These individual checks can be nested in different grouped set of validations. Validators all implement the Validator interface to allow simple nesting of checks.

There are three types of validators:

1. **Atomic Validators:** they validate an individual field or several fields and contain actual checking of certain values, checking of an anchor etc. Atomic validators are never split up. Anything an atomic validator validates would always be validated as one block.

2. **Internal Group Validations:** contain a collection of atomic validators but these are not grouped by purpose but elements that are reused in other validators (group or purpose validators)

3. **Purpose Validators:** these validators are public and used by the application logic to validate a document. They should never be used inside of other validators. Code performing validation should always call a purpose validator but never an internal group directly.

type interface Validator {
// Validate validates the updates to the model in newState. errors returned must always be centerrors
Validate(oldState Model, newState Model) []error
}

// ValidatorGroup implements Validator for executing a set of validators.
type ValidatorGroup struct {
[]Validator validators
}
func (group *ValidatorGroup) Validate(oldState Model, newState Model) (validationErrors []error) {

for v, i := range group.validators {
validationErrors = append(validationErrors, v.Validate(oldState, newState))
}
}

// An implementation of ValidatorGroup as an example.
// Note that this is not a public validator but merely a private variable that can be reused in validators.
var invoiceHeaderValidators = ValidatorGroup{
validators: []Validator{
Field1Validator,
Field2Validator,
Field3Validator
}
}

// An implementation of a Validator that is used by other services
// Note that this is public
var ValidateOnSignatureRequest = ValidatorGroup{
validators: []Validator{
invoiceHeaderValidator, ...
}
}

Controllers, Services and Their Relationship with Models

1. Controllers

Controllers are generally the first contact point between an external request and the application logic. The implementations would just pass control over to a request specific `Service` layer call.

2. Services

Services in the CentNode must deal with only specific Model object plus its related objects. Eg: InvoiceService would only deal with InvoiceModel. Since in many cases a model object may need to be created based on some external input such as a coredocument, the following are some good base interfaces for a service to implement,

// Implementation of deriving model objects
type InvoiceService struct { }

func (srv *InvoiceService) DeriveFromCoreDocument(cd *coredocument.CoreDocument) (*InvoiceModel, error) {
panic("Implement me");
}

func (srv *InvoiceService)  DeriveWithCreateInvoiceInput(*CreateInvoiceInput) (*InvoiceModel, error) {
panic("Implement me");
}

Service Registry

To locate a service that could handle operations for a given CoreDocument object a service registry needs to be developed. This would use the `coreDocument.EmbeddedData.TypeUrl` to map the document to the relevant service.

// in documents/registry.go

func LocateService(cd *coredocument.CoreDocument) (ModelDeriver, error) {
....
}

Every service should be able to `register` itself at the `ServiceRegistry` if it implements the `ModelDeriver` interface.

func (s *ServiceRegistry) Register(serviceID string, service ModelDeriver) error

The registry should be thread safe.

A Sample Flow for Handling Document Signature Requests

The following is an example modification of `Handler.RequestDocumentSignature` to show the usage of `Registry`, `Service` and `Model` interactions.

func (srv *Handler) RequestDocumentSignature(ctx context.Context, sigReq *p2ppb.SignatureRequest) (*p2ppb.SignatureResponse, error) {
service, err := registry.LocateService(sigReq.Document)
if err != nil {
return nil, err
}

model, err := service.DeriveWithCD(sigReq.Document)
if err != nil {
return nil, err
}

if p2pService, ok := service.(P2PSignatureRequestHandler); ok {
sig, errors := p2pService.Sign(model)
if len(errs) != 0 {
return nil, centerrors.NewWithErrors(errs)
}
return &p2ppb.SignatureResponse{
CentNodeVersion: version.GetVersion().String(),
Signature:       sig,
}, nil
}

return nil, someerrorThatcausedServiceMismatch

}

Index

Constants

View Source
const (
	// DocumentIDParam maps to model ID in the kwargs
	DocumentIDParam = "documentID"

	// AccountIDParam maps to account ID in the kwargs
	AccountIDParam = "accountID"
)
View Source
const (
	// BootstrappedRegistry is the key to ServiceRegistry in Bootstrap context
	BootstrappedRegistry = "BootstrappedRegistry"

	// BootstrappedDocumentRepository is the key to the database repository of documents
	BootstrappedDocumentRepository = "BootstrappedDocumentRepository"

	// BootstrappedDocumentService is the key to bootstrapped document service
	BootstrappedDocumentService = "BootstrappedDocumentService"

	// BootstrappedAnchorProcessor is the key to bootstrapped anchor processor
	BootstrappedAnchorProcessor = "BootstrappedAnchorProcessor"
)
View Source
const (
	// CDRootField represents the coredocument root property of a tree
	CDRootField = "cd_root"

	// DataRootField represents the data root property of a tree
	DataRootField = "data_root"

	// DocumentTypeField represents the doc type property of a tree
	DocumentTypeField = "document_type"

	// SignaturesRootField represents the signatures property of a tree
	SignaturesRootField = "signatures_root"

	// SigningRootField represents the signature root property of a tree
	SigningRootField = "signing_root"

	// DRTreePrefix is the human readable prefix for document root tree props
	DRTreePrefix = "dr_tree"

	// CDTreePrefix is the human readable prefix for core doc tree props
	CDTreePrefix = "cd_tree"

	// SigningTreePrefix is the human readable prefix for signing tree props
	SigningTreePrefix = "signing_tree"

	// SignaturesTreePrefix is the human readable prefix for signature props
	SignaturesTreePrefix = "signatures_tree"
)
View Source
const (

	// ErrDocumentConfigAccountID must be used for errors related to accountID operations
	ErrDocumentConfigAccountID = errors.Error("error with accountID operations")

	// ErrDocumentBootstrap must be used for errors related to documents package bootstrapping
	ErrDocumentBootstrap = errors.Error("error when bootstrapping documents package")

	// ErrDocumentIdentifier must be used for errors caused by document identifier problems
	ErrDocumentIdentifier = errors.Error("document identifier error")

	// ErrDocumentInvalidType must be used when a provided document type is not valid to be processed by the service
	ErrDocumentInvalidType = errors.Error("document is of invalid type")

	// ErrDocumentNil must be used when the provided document through a function is nil
	ErrDocumentNil = errors.Error("no(nil) document provided")

	// ErrPayloadNil must be used when a required payload is nil
	ErrPayloadNil = errors.Error("no(nil) payload provided")

	// ErrDocumentNotification must be used when a notification about a document could not be delivered
	ErrDocumentNotification = errors.Error("could not notify of the document")

	// ErrDocumentInvalid must only be used when the reason for invalidity is impossible to determine or the invalidity is caused by validation errors
	ErrDocumentInvalid = errors.Error("document is invalid")

	// ErrDocumentNotFound must be used to indicate that the document for provided id is not found in the system
	ErrDocumentNotFound = errors.Error("document not found in the system database")

	// ErrNoCollaborator must be used to indicate that the document for provided id the user is not a collaborator
	ErrNoCollaborator = errors.Error("no collaborator on the document")

	// ErrDocumentVersionNotFound must be used to indicate that the specified version of the document for provided id is not found in the system
	ErrDocumentVersionNotFound = errors.Error("specified version of the document not found in the system database")

	// ErrDocumentPersistence must be used when creating or updating a document in the system database failed
	ErrDocumentPersistence = errors.Error("error encountered when storing document in the system database")

	// ErrDocumentUnPackingCoreDocument must be used when unpacking of core document for the given document failed
	ErrDocumentUnPackingCoreDocument = errors.Error("core document unpacking failed")

	// ErrDocumentPrepareCoreDocument must be used when preparing a new core document fails for the given document
	ErrDocumentPrepareCoreDocument = errors.Error("core document preparation failed")

	// ErrDocumentAnchoring must be used when document anchoring fails
	ErrDocumentAnchoring = errors.Error("document anchoring failed")

	// ErrDocumentProof must be used when document proof creation fails
	ErrDocumentProof = errors.Error("document proof error")

	// ErrCDCreate must be used for coredoc creation/generation errors
	ErrCDCreate = errors.Error("error creating core document")

	// ErrCollaborators must be used when collaborators are not valid
	ErrCollaborators = errors.Error("invalid collaborators")

	// ErrCDTree must be used when there are errors during precise-proof tree and root generation
	ErrCDTree = errors.Error("error when generating trees/roots")

	// ErrCDAttribute must be used when there are errors caused by custom model attributes
	ErrCDAttribute = errors.Error("model attribute error")

	// ErrNftNotFound must be used when the NFT is not found in the document
	ErrNftNotFound = errors.Error("nft not found in the Document")

	// ErrNftByteLength must be used when there is a byte length mismatch
	ErrNftByteLength = errors.Error("byte length mismatch")

	// ErrAccessTokenInvalid must be used when the access token is invalid
	ErrAccessTokenInvalid = errors.Error("access token is invalid")

	// ErrAccessTokenNotFound must be used when the access token was not found
	ErrAccessTokenNotFound = errors.Error("access token not found")

	// ErrRequesterNotGrantee must be used when the document requester is not the grantee of the access token
	ErrRequesterNotGrantee = errors.Error("requester is not the same as the access token grantee")

	// ErrGranterNotCollab must be used when the granter of the access token is not a collaborator on the document
	ErrGranterNotCollab = errors.Error("access token granter is not a collaborator on this document")

	// ErrReqDocNotMatch must be used when the requested document does not match the access granted by the access token
	ErrReqDocNotMatch = errors.Error("the document requested does not match the document to which the access token grants access")

	// ErrNFTRoleMissing errors when role to generate proof doesn't exist
	ErrNFTRoleMissing = errors.Error("NFT Role doesn't exist")

	// ErrInvalidIDLength must be used when the identifier bytelength is not 32
	ErrInvalidIDLength = errors.Error("invalid identifier length")

	// ErrDocumentAnchor must be used if it is not possible to access an anchor from chain
	ErrDocumentAnchor = errors.Error("failed to get document anchor from chain")

	// ErrDocumentNotLatest must be used if document is not the latest version
	ErrDocumentNotLatest = errors.Error("document is not the latest version")

	// ErrModelNil must be used if the model is nil
	ErrModelNil = errors.Error("model is empty")

	// ErrInvalidDecimal must be used when given decimal is invalid
	ErrInvalidDecimal = errors.Error("invalid decimal")

	// ErrIdentityNotOwner must be used when an identity which does not own the entity relationship attempts to update the document
	ErrIdentityNotOwner = errors.Error("identity attempting to update the document does not own this entity relationship")

	// ErrNotImplemented must be used when an method has not been implemented
	ErrNotImplemented = errors.Error("Method not implemented")
)
View Source
const MaxAuthoredToCommitDuration = 120 * time.Minute

MaxAuthoredToCommitDuration is the maximum allowed time period for a document to be anchored after a authoring it based on document timestamp. I.E. This is basically the maximum time period allowed for document consensus to complete as well.

Variables

This section is empty.

Functions

func CompactProperties

func CompactProperties(key string) []byte

CompactProperties returns the compact property for a given prefix

func ConstructNFT

func ConstructNFT(registry common.Address, tokenID []byte) ([]byte, error)

ConstructNFT appends registry and tokenID to byte slice

func ConvertDocProofToClientFormat

func ConvertDocProofToClientFormat(proof *DocumentProof) (*documentpb.DocumentProof, error)

ConvertDocProofToClientFormat converts a DocumentProof to client api format

func ConvertProofToClientFormat

func ConvertProofToClientFormat(proof *proofspb.Proof) *documentpb.Proof

ConvertProofToClientFormat converts a proof in precise proof format in to a client protobuf proof

func ConvertProofsToClientFormat

func ConvertProofsToClientFormat(proofs []*proofspb.Proof) []*documentpb.Proof

ConvertProofsToClientFormat converts a proof protobuf from precise proofs into a client protobuf proof format

func CreateAnchorTransaction

func CreateAnchorTransaction(jobMan jobs.Manager, tq queue.TaskQueuer, self identity.DID, jobID jobs.JobID, documentID []byte) (jobs.JobID, chan bool, error)

CreateAnchorTransaction creates a transaction for anchoring a document using transaction manager

func DecimalsToBytes

func DecimalsToBytes(decs ...*Decimal) ([][]byte, error)

DecimalsToBytes converts decimals to bytes

func DecimalsToStrings

func DecimalsToStrings(decs ...*Decimal) []string

DecimalsToStrings converts decimals to string. nil decimal leads to empty string.

func DeriveResponseHeader

func DeriveResponseHeader(tokenRegistry TokenRegistry, model Model) (*documentpb.ResponseHeader, error)

DeriveResponseHeader derives common response header for model

func GRPCHandler

func GRPCHandler(config config.Service, registry *ServiceRegistry) documentpb.DocumentServiceServer

GRPCHandler returns an implementation of documentpb.DocumentServiceServer

func InitDocumentAnchorTask

func InitDocumentAnchorTask(jobMan jobs.Manager, tq queue.TaskQueuer, accountID identity.DID, modelID []byte, txID jobs.JobID) (queue.TaskResult, error)

InitDocumentAnchorTask enqueues a new document anchor task for a given combination of accountID/modelID/txID.

func IsCurrencyValid

func IsCurrencyValid(cur string) bool

IsCurrencyValid checks if the currency is of length 3

func NewError

func NewError(key, msg string) error

NewError creates a new error from a key and a msg. Deprecated: in favour of Error type in `github.com/centrifuge/go-centrifuge/errors`

func NewLeafProperty

func NewLeafProperty(literal string, compact []byte) proofs.Property

NewLeafProperty returns a proof property with the literal and the compact

func ToClientAttachments

func ToClientAttachments(atts []*BinaryAttachment) []*documentpb.BinaryAttachment

ToClientAttachments converts Attachments to Client Attachments.

func ToClientCollaboratorAccess

func ToClientCollaboratorAccess(ca CollaboratorsAccess) (*documentpb.ReadAccess, *documentpb.WriteAccess)

ToClientCollaboratorAccess converts CollaboratorAccess to client collaborator access

func ToClientPaymentDetails

func ToClientPaymentDetails(details []*PaymentDetails) []*documentpb.PaymentDetails

ToClientPaymentDetails converts PaymentDetails to client payment details.

func ToP2PAttachments

func ToP2PAttachments(atts []*BinaryAttachment) []*commonpb.BinaryAttachment

ToP2PAttachments converts Binary Attchments to P2P attachments.

func ToP2PPaymentDetails

func ToP2PPaymentDetails(details []*PaymentDetails) ([]*commonpb.PaymentDetails, error)

ToP2PPaymentDetails converts payment details to P2P payment details

func ValidateTransitions

func ValidateTransitions(rules []coredocumentpb.TransitionRule, changedFields []ChangedField) error

ValidateTransitions validates the changedFields based on the rules provided. returns an error if any ChangedField violates the rules.

Types

type AllowedAttributeType

type AllowedAttributeType string

AllowedAttributeType represents the custom attribute types allowed in models

const (
	// Int256Type is the standard integer custom attribute type
	Int256Type AllowedAttributeType = "int256"

	// BigDecType is the standard big decimal custom attribute type
	BigDecType AllowedAttributeType = "bigdecimal"

	// StrType is the standard string custom attribute type
	StrType AllowedAttributeType = "string"

	// BytsType is the standard bytes custom attribute type
	BytsType AllowedAttributeType = "bytes"

	// TimestmpType is the standard time stamp custom attribute type
	TimestmpType AllowedAttributeType = "timestamp"
)

func (AllowedAttributeType) String

func (a AllowedAttributeType) String() string

String string repr

type AnchorProcessor

type AnchorProcessor interface {
	Send(ctx context.Context, cd coredocumentpb.CoreDocument, recipient identity.DID) (err error)
	PrepareForSignatureRequests(ctx context.Context, model Model) error
	RequestSignatures(ctx context.Context, model Model) error
	PrepareForAnchoring(model Model) error
	PreAnchorDocument(ctx context.Context, model Model) error
	AnchorDocument(ctx context.Context, model Model) error
	SendDocument(ctx context.Context, model Model) error
}

AnchorProcessor identifies an implementation, which can do a bunch of things with a CoreDocument. E.g. send, anchor, etc.

func DefaultProcessor

func DefaultProcessor(idService identity.ServiceDID, p2pClient Client, repository anchors.AnchorRepository, config Config) AnchorProcessor

DefaultProcessor returns the default implementation of CoreDocument AnchorProcessor

type BinaryAttachment

type BinaryAttachment struct {
	Name     string
	FileType string // mime type of attached file
	Size     uint64 // in bytes
	Data     []byte
	Checksum []byte // the md5 checksum of the original file for easier verification
}

BinaryAttachment represent a single file attached to invoice.

func FromClientAttachments

func FromClientAttachments(catts []*documentpb.BinaryAttachment) ([]*BinaryAttachment, error)

FromClientAttachments converts Client Attachments to Binary Attachments

func FromP2PAttachments

func FromP2PAttachments(patts []*commonpb.BinaryAttachment) []*BinaryAttachment

FromP2PAttachments converts P2P attachments to Binary Attchments

type Bootstrapper

type Bootstrapper struct{}

Bootstrapper implements bootstrap.Bootstrapper.

func (Bootstrapper) Bootstrap

func (Bootstrapper) Bootstrap(ctx map[string]interface{}) error

Bootstrap sets the required storage and registers

type ChangedField

type ChangedField struct {
	Property, Old, New []byte
	Name               string
}

ChangedField holds the compact property, old and new value of the field that is changed if the old is nil, then it is a set operation if new is nil, then it is an unset operation if both old and new are set, then it is an edit operation

func GetChangedFields

func GetChangedFields(oldTree, newTree *proofs.DocumentTree) (changedFields []ChangedField)

GetChangedFields takes two document trees and returns the compact property, old and new value of the fields that are changed in new tree. Properties may have been added to the new tree or removed from the new tree. In Either case, since the new tree is different from old, that is considered a change.

type Client

type Client interface {

	// GetSignaturesForDocument gets the signatures for document
	GetSignaturesForDocument(ctx context.Context, model Model) ([]*coredocumentpb.Signature, []error, error)

	// after all signatures are collected the sender sends the document including the signatures
	SendAnchoredDocument(ctx context.Context, receiverID identity.DID, in *p2ppb.AnchorDocumentRequest) (*p2ppb.AnchorDocumentResponse, error)

	// GetDocumentRequest requests a document from a collaborator
	GetDocumentRequest(ctx context.Context, requesterID identity.DID, in *p2ppb.GetDocumentRequest) (*p2ppb.GetDocumentResponse, error)
}

Client defines methods that can be implemented by any type handling p2p communications.

type CollaboratorsAccess

type CollaboratorsAccess struct {
	ReadCollaborators      []identity.DID
	ReadWriteCollaborators []identity.DID
}

CollaboratorsAccess allows us to differentiate between the types of access we want to give new collaborators

func FromClientCollaboratorAccess

func FromClientCollaboratorAccess(racess *documentpb.ReadAccess, waccess *documentpb.WriteAccess) (ca CollaboratorsAccess, err error)

FromClientCollaboratorAccess converts client collaborator access to CollaboratorsAccess

type Config

type Config interface {
	GetNetworkID() uint32
	GetIdentityID() ([]byte, error)
	GetP2PConnectionTimeout() time.Duration
}

Config defines required methods required for the documents package.

type CoreDocument

type CoreDocument struct {
	// Modified indicates that the CoreDocument has been modified and salts needs to be generated for new fields in coredoc precise-proof tree.
	Modified bool

	// Attributes are the custom attributes added to the document
	Attributes map[string]*attribute

	Document coredocumentpb.CoreDocument
}

CoreDocument is a wrapper for CoreDocument Protobuf.

func NewCoreDocumentFromProtobuf

func NewCoreDocumentFromProtobuf(cd coredocumentpb.CoreDocument) *CoreDocument

NewCoreDocumentFromProtobuf returns CoreDocument from the CoreDocument Protobuf.

func NewCoreDocumentWithAccessToken

func NewCoreDocumentWithAccessToken(ctx context.Context, documentPrefix []byte, params documentpb.AccessTokenParams) (*CoreDocument, error)

NewCoreDocumentWithAccessToken generates a new core document with a document type specified by the prefix. It also adds the targetID as a read collaborator, and adds an access token on this document for the document specified in the documentID parameter

func NewCoreDocumentWithCollaborators

func NewCoreDocumentWithCollaborators(documentPrefix []byte, collaborators CollaboratorsAccess) (*CoreDocument, error)

NewCoreDocumentWithCollaborators generates new core document with a document type specified by the prefix: po or invoice. It then adds collaborators, adds read rules and fills salts.

func (*CoreDocument) ATGranteeCanRead

func (cd *CoreDocument) ATGranteeCanRead(ctx context.Context, docService Service, idService identity.ServiceDID, tokenID, docID []byte, requesterID identity.DID) (err error)

ATGranteeCanRead checks that the grantee of the access token can read the document requested

func (*CoreDocument) AccountCanRead

func (cd *CoreDocument) AccountCanRead(account identity.DID) bool

AccountCanRead validate if the core document can be read by the account . Returns an error if not.

func (*CoreDocument) AddAccessToken

func (cd *CoreDocument) AddAccessToken(ctx context.Context, payload documentpb.AccessTokenParams) (*CoreDocument, error)

AddAccessToken adds the AccessToken to the document

func (*CoreDocument) AddAttribute

func (cd *CoreDocument) AddAttribute(name string, attributeType AllowedAttributeType, value string) error

AddAttribute adds a custom attribute to the model with the given value. If an attribute with the given name already exists, it's updated.

func (*CoreDocument) AddNFT

func (cd *CoreDocument) AddNFT(grantReadAccess bool, registry common.Address, tokenID []byte) (*CoreDocument, error)

AddNFT returns a new CoreDocument model with nft added to the Core document. If grantReadAccess is true, the nft is added to the read rules.

func (*CoreDocument) AddUpdateLog

func (cd *CoreDocument) AddUpdateLog(account identity.DID) (err error)

AddUpdateLog adds a log to the model to persist an update related meta data such as author

func (*CoreDocument) AppendSignatures

func (cd *CoreDocument) AppendSignatures(signs ...*coredocumentpb.Signature)

AppendSignatures appends signatures to core document.

func (*CoreDocument) Author

func (cd *CoreDocument) Author() (identity.DID, error)

Author is the author of the document version represented by the model

func (*CoreDocument) CalculateDocumentRoot

func (cd *CoreDocument) CalculateDocumentRoot(docType string, dataRoot []byte) ([]byte, error)

CalculateDocumentRoot calculates the document root of the CoreDocument.

func (*CoreDocument) CalculateSignaturesRoot

func (cd *CoreDocument) CalculateSignaturesRoot() ([]byte, error)

CalculateSignaturesRoot returns the signatures root of the document.

func (*CoreDocument) CalculateSigningRoot

func (cd *CoreDocument) CalculateSigningRoot(docType string, dataRoot []byte) ([]byte, error)

CalculateSigningRoot calculates the signing root of the core document.

func (*CoreDocument) CollaboratorCanUpdate

func (cd *CoreDocument) CollaboratorCanUpdate(ncd *CoreDocument, collaborator identity.DID, docType string) error

CollaboratorCanUpdate validates the changes made by the collaborator in the new document. returns error if the transitions are not allowed for the collaborator.

func (*CoreDocument) CreateNFTProofs

func (cd *CoreDocument) CreateNFTProofs(
	docType string,
	dataTree *proofs.DocumentTree,
	account identity.DID,
	registry common.Address,
	tokenID []byte,
	nftUniqueProof, readAccessProof bool) (prfs []*proofspb.Proof, err error)

CreateNFTProofs generate proofs returns proofs for NFT minting.

func (*CoreDocument) CreateProofs

func (cd *CoreDocument) CreateProofs(docType string, dataTree *proofs.DocumentTree, fields []string) (prfs []*proofspb.Proof, err error)

CreateProofs takes document data tree and list to fields and generates proofs. we will try generating proofs from the dataTree. If failed, we will generate proofs from CoreDocument. errors out when the proof generation is failed on core document tree.

func (*CoreDocument) CurrentVersion

func (cd *CoreDocument) CurrentVersion() []byte

CurrentVersion returns the current version of the document

func (*CoreDocument) CurrentVersionPreimage

func (cd *CoreDocument) CurrentVersionPreimage() []byte

CurrentVersionPreimage returns the current version preimage of the document

func (*CoreDocument) DefaultTreeWithPrefix

func (cd *CoreDocument) DefaultTreeWithPrefix(prefix string, compactPrefix []byte) *proofs.DocumentTree

DefaultTreeWithPrefix returns a DocumentTree with default opts passing a prefix to the tree leaves

func (*CoreDocument) DeleteAccessToken

func (cd *CoreDocument) DeleteAccessToken(ctx context.Context, granteeID string) (*CoreDocument, error)

DeleteAccessToken deletes an access token on the Document

func (*CoreDocument) DeleteAttribute

func (cd *CoreDocument) DeleteAttribute(name string) error

DeleteAttribute deletes a custom attribute from the model

func (*CoreDocument) DocumentRootTree

func (cd *CoreDocument) DocumentRootTree(docType string, dataRoot []byte) (tree *proofs.DocumentTree, err error)

DocumentRootTree returns the merkle tree for the document root.

func (*CoreDocument) DocumentSaltsFunc

func (cd *CoreDocument) DocumentSaltsFunc() func(compact []byte) ([]byte, error)

DocumentSaltsFunc returns a function that fetches and sets salts on the CoreDoc. The boolean `cd.Modified` can be used to define if the salts function should error if a new field is encountered or not.

func (*CoreDocument) GetAccessTokens

func (cd *CoreDocument) GetAccessTokens() ([]*coredocumentpb.AccessToken, error)

GetAccessTokens returns the access tokens of a core document

func (*CoreDocument) GetAttribute

func (cd *CoreDocument) GetAttribute(name string) (hashedKey []byte, attrType string, value interface{}, valueStr string, err error)

GetAttribute gets the attribute with the given name from the model together with its type, it returns a non-nil error if the attribute doesn't exist or can't be retrieved.

func (*CoreDocument) GetCollaborators

func (cd *CoreDocument) GetCollaborators(filterIDs ...identity.DID) (CollaboratorsAccess, error)

GetCollaborators returns the collaborators excluding the filteredIDs

func (*CoreDocument) GetSignerCollaborators

func (cd *CoreDocument) GetSignerCollaborators(filterIDs ...identity.DID) ([]identity.DID, error)

GetSignerCollaborators returns the collaborators excluding the filteredIDs returns collaborators with Read_Sign permissions.

func (*CoreDocument) ID

func (cd *CoreDocument) ID() []byte

ID returns the document identifier

func (*CoreDocument) IsDIDCollaborator

func (cd *CoreDocument) IsDIDCollaborator(did identity.DID) (bool, error)

IsDIDCollaborator returns true if the did is a collaborator of the document

func (*CoreDocument) IsNFTMinted

func (cd *CoreDocument) IsNFTMinted(tokenRegistry TokenRegistry, registry common.Address) bool

IsNFTMinted checks if the there is an NFT that is minted against this document in the given registry.

func (*CoreDocument) NFTOwnerCanRead

func (cd *CoreDocument) NFTOwnerCanRead(tokenRegistry TokenRegistry, registry common.Address, tokenID []byte, account identity.DID) error

NFTOwnerCanRead checks if the nft owner/account can read the Document

func (*CoreDocument) NFTs

func (cd *CoreDocument) NFTs() []*coredocumentpb.NFT

NFTs returns the list of NFTs created for this model

func (*CoreDocument) NextVersion

func (cd *CoreDocument) NextVersion() []byte

NextVersion returns the next version of the document.

func (*CoreDocument) PackCoreDocument

func (cd *CoreDocument) PackCoreDocument(data *any.Any) coredocumentpb.CoreDocument

PackCoreDocument prepares the document into a core document.

func (*CoreDocument) PrepareNewVersion

func (cd *CoreDocument) PrepareNewVersion(documentPrefix []byte, collaborators CollaboratorsAccess) (*CoreDocument, error)

PrepareNewVersion prepares the next version of the CoreDocument if initSalts is true, salts will be generated for new version.

func (*CoreDocument) PreviousVersion

func (cd *CoreDocument) PreviousVersion() []byte

PreviousVersion returns the previous version of the document.

func (*CoreDocument) Signatures

func (cd *CoreDocument) Signatures() (signatures []coredocumentpb.Signature)

Signatures returns the copy of the signatures on the document.

func (*CoreDocument) Timestamp

func (cd *CoreDocument) Timestamp() (time.Time, error)

Timestamp is the time of update in UTC of the document version represented by the model

func (*CoreDocument) TransitionRulesFor

func (cd *CoreDocument) TransitionRulesFor(did identity.DID) (rules []coredocumentpb.TransitionRule)

TransitionRulesFor returns a copy all the transition rules for the DID.

type Decimal

type Decimal struct {
	// contains filtered or unexported fields
}

Decimal holds a fixed point decimal

func BytesToDecimals

func BytesToDecimals(bytes ...[]byte) ([]*Decimal, error)

BytesToDecimals converts decimals in bytes to Decimal type

func StringsToDecimals

func StringsToDecimals(strs ...string) ([]*Decimal, error)

StringsToDecimals converts string decimals to Decimal type

func (*Decimal) Bytes

func (d *Decimal) Bytes() (decimal []byte, err error)

Bytes return the decimal in bytes. sign byte + upto 23 integer bytes + 8 decimal bytes

func (*Decimal) MarshalJSON

func (d *Decimal) MarshalJSON() ([]byte, error)

MarshalJSON marshals decimal to json bytes.

func (*Decimal) SetBytes

func (d *Decimal) SetBytes(dec []byte) error

SetBytes parse the bytes to Decimal.

func (*Decimal) SetString

func (d *Decimal) SetString(s string) error

SetString takes a decimal in string format and converts it into Decimal

func (*Decimal) String

func (d *Decimal) String() string

String returns the decimal in string representation.

func (*Decimal) UnmarshalJSON

func (d *Decimal) UnmarshalJSON(data []byte) error

UnmarshalJSON loads json bytes to decimal

type DocumentProof

type DocumentProof struct {
	DocumentID  []byte
	VersionID   []byte
	State       string
	FieldProofs []*proofspb.Proof
}

DocumentProof is a value to represent a document and its field proofs

type DocumentRequestProcessor

type DocumentRequestProcessor interface {
	RequestDocumentWithAccessToken(ctx context.Context, granterDID identity.DID, tokenIdentifier, entityIdentifier, entityRelationIdentifier []byte) (*p2ppb.GetDocumentResponse, error)
}

DocumentRequestProcessor offers methods to interact with the p2p layer to request documents.

type Error

type Error struct {
	// contains filtered or unexported fields
}

Error wraps an error with specific key Deprecated: in favour of Error type in `github.com/centrifuge/go-centrifuge/errors`

func (Error) Error

func (e Error) Error() string

Error returns the underlying error message

type Model

type Model interface {
	storage.Model

	// ID returns the document identifier
	ID() []byte

	// CurrentVersion returns the current version identifier of the document
	CurrentVersion() []byte

	// CurrentVersionPreimage returns the current version pre-image of the document. This is intended to hide the next version of an updated version of the document.
	CurrentVersionPreimage() []byte

	// PreviousVersion returns the previous version identifier of the document
	PreviousVersion() []byte

	// NextVersion returns the next version identifier of the document.
	NextVersion() []byte

	// PackCoreDocument packs the implementing document into a core document
	// Should only be called when the document is about to be put on wire.
	PackCoreDocument() (coredocumentpb.CoreDocument, error)

	// UnpackCoreDocument takes a core document protobuf and loads the data into the model.
	UnpackCoreDocument(cd coredocumentpb.CoreDocument) error

	// DocumentType returns the type of the document
	DocumentType() string

	// CalculateDataRoot calculates the data root of the model.
	CalculateDataRoot() ([]byte, error)

	// CalculateSigningRoot calculates the signing root of the model.
	CalculateSigningRoot() ([]byte, error)

	// CalculateDocumentRoot returns the document root of the model.
	CalculateDocumentRoot() ([]byte, error)

	// CalculateSignaturesRoot returns signatures root of the model.
	CalculateSignaturesRoot() ([]byte, error)

	// DocumentRootTree returns the document root tree
	DocumentRootTree() (tree *proofs.DocumentTree, err error)

	// AppendSignatures appends the signatures to the model.
	AppendSignatures(signatures ...*coredocumentpb.Signature)

	// Signatures returns a copy of the signatures on the document
	Signatures() []coredocumentpb.Signature

	// CreateProofs creates precise-proofs for given fields
	CreateProofs(fields []string) (proofs []*proofspb.Proof, err error)

	// CreateNFTProofs creates NFT proofs for minting.
	CreateNFTProofs(
		account identity.DID,
		registry common.Address,
		tokenID []byte,
		nftUniqueProof, readAccessProof bool) (proofs []*proofspb.Proof, err error)

	// IsNFTMinted checks if there is any NFT minted for the registry given
	IsNFTMinted(tr TokenRegistry, registry common.Address) bool

	// AddNFT adds an NFT to the document.
	// Note: The document should be anchored after successfully adding the NFT.
	AddNFT(grantReadAccess bool, registry common.Address, tokenID []byte) error

	// NFTs returns the list of NFTs created for this model
	NFTs() []*coredocumentpb.NFT

	// GetCollaborators returns the collaborators of this document.
	// filter ids should not be returned
	// Note: returns all the collaborators with Read and Read_Sign permission
	GetCollaborators(filterIDs ...identity.DID) (CollaboratorsAccess, error)

	// GetSignerCollaborators works like GetCollaborators except it returns only those with Read_Sign permission.
	GetSignerCollaborators(filterIDs ...identity.DID) ([]identity.DID, error)

	// AccountCanRead returns true if the account can read the document
	AccountCanRead(account identity.DID) bool

	// NFTOwnerCanRead returns error if the NFT cannot read the document.
	NFTOwnerCanRead(tokenRegistry TokenRegistry, registry common.Address, tokenID []byte, account identity.DID) error

	// ATGranteeCanRead returns error if the access token grantee cannot read the document.
	ATGranteeCanRead(ctx context.Context, docSrv Service, idSrv identity.ServiceDID, tokenID, docID []byte, grantee identity.DID) (err error)

	// AddUpdateLog adds a log to the model to persist an update related meta data such as author
	AddUpdateLog(account identity.DID) error

	// Author is the author of the document version represented by the model
	Author() (identity.DID, error)

	// Timestamp is the time of update in UTC of the document version represented by the model
	Timestamp() (time.Time, error)

	// CollaboratorCanUpdate returns an error if indicated identity does not have the capacity to update the document.
	CollaboratorCanUpdate(updated Model, collaborator identity.DID) error

	// IsDIDCollaborator returns true if the did is a collaborator of the document
	IsDIDCollaborator(did identity.DID) (bool, error)

	// AddAttribute adds a custom attribute to the model with the given value. If an attribute with the given name already exists, it's updated.
	AddAttribute(name string, attributeType AllowedAttributeType, value string) error

	// GetAttribute gets the attribute with the given name from the model, it returns a non-nil error if the attribute doesn't exist or can't be retrieved.
	GetAttribute(name string) (hashedKey []byte, attrType string, value interface{}, valueStr string, err error)

	// DeleteAttribute deletes a custom attribute from the model
	DeleteAttribute(name string) error

	// GetAccessTokens returns the access tokens of a core document
	GetAccessTokens() ([]*coredocumentpb.AccessToken, error)
}

Model is an interface to abstract away model specificness like invoice or purchaseOrder The interface can cast into the type specified by the model if required It should only handle protocol-level document actions

func AnchorDocument

func AnchorDocument(ctx context.Context, model Model, proc AnchorProcessor, updater updaterFunc, preAnchor bool) (Model, error)

AnchorDocument add signature, requests signatures, anchors document, and sends the anchored document to collaborators

type PaymentDetails

type PaymentDetails struct {
	ID                    string // identifying this payment. could be a sequential number, could be a transaction hash of the crypto payment
	DateExecuted          *timestamp.Timestamp
	Payee                 *identity.DID // centrifuge id of payee
	Payer                 *identity.DID // centrifuge id of payer
	Amount                *Decimal
	Currency              string
	Reference             string // payment reference (e.g. reference field on bank transfer)
	BankName              string
	BankAddress           string
	BankCountry           string
	BankAccountNumber     string
	BankAccountCurrency   string
	BankAccountHolderName string
	BankKey               string

	CryptoChainURI      string // the ID of the chain to use in URI format. e.g. "ethereum://42/<tokenaddress>"
	CryptoTransactionID string // the transaction in which the payment happened
	CryptoFrom          string // from address
	CryptoTo            string // to address
}

PaymentDetails holds the payment related details for invoice.

func FromClientPaymentDetails

func FromClientPaymentDetails(cdetails []*documentpb.PaymentDetails) ([]*PaymentDetails, error)

FromClientPaymentDetails converts Client PaymentDetails to PaymentDetails

func FromP2PPaymentDetails

func FromP2PPaymentDetails(pdetails []*commonpb.PaymentDetails) ([]*PaymentDetails, error)

FromP2PPaymentDetails converts P2P payment details to PaymentDetails

type PostBootstrapper

type PostBootstrapper struct{}

PostBootstrapper to run the post after all bootstrappers.

func (PostBootstrapper) Bootstrap

func (PostBootstrapper) Bootstrap(ctx map[string]interface{}) error

Bootstrap register task to the queue.

type Repository

type Repository interface {
	// Exists checks if the id, owned by accountID, exists in DB
	Exists(accountID, id []byte) bool

	// Get returns the Model associated with ID, owned by accountID
	Get(accountID, id []byte) (Model, error)

	// Create creates the model if not present in the DB.
	// should error out if the document exists.
	Create(accountID, id []byte, model Model) error

	// Update strictly updates the model.
	// Will error out when the model doesn't exist in the DB.
	Update(accountID, id []byte, model Model) error

	// Register registers the model so that the DB can return the document without knowing the type
	Register(model Model)
}

Repository defines the required methods for a document repository. Can be implemented by any type that stores the documents. Ex: levelDB, sql etc...

func NewDBRepository

func NewDBRepository(db storage.Repository) Repository

NewDBRepository creates an instance of the documents Repository

type Service

type Service interface {

	// GetCurrentVersion reads a document from the database
	GetCurrentVersion(ctx context.Context, documentID []byte) (Model, error)

	// Exists checks if a document exists
	Exists(ctx context.Context, documentID []byte) bool

	// GetVersion reads a document from the database
	GetVersion(ctx context.Context, documentID []byte, version []byte) (Model, error)

	// DeriveFromCoreDocument derives a model given the core document.
	DeriveFromCoreDocument(cd coredocumentpb.CoreDocument) (Model, error)

	// CreateProofs creates proofs for the latest version document given the fields
	CreateProofs(ctx context.Context, documentID []byte, fields []string) (*DocumentProof, error)

	// CreateProofsForVersion creates proofs for a particular version of the document given the fields
	CreateProofsForVersion(ctx context.Context, documentID, version []byte, fields []string) (*DocumentProof, error)

	// RequestDocumentSignature Validates and Signs document received over the p2p layer
	RequestDocumentSignature(ctx context.Context, model Model, collaborator identity.DID) (*coredocumentpb.Signature, error)

	// ReceiveAnchoredDocument receives a new anchored document over the p2p layer, validates and updates the document in DB
	ReceiveAnchoredDocument(ctx context.Context, model Model, collaborator identity.DID) error

	// Create validates and persists Model and returns a Updated model
	Create(ctx context.Context, model Model) (Model, jobs.JobID, chan bool, error)

	// Update validates and updates the model and return the updated model
	Update(ctx context.Context, model Model) (Model, jobs.JobID, chan bool, error)
}

Service provides an interface for functions common to all document types

func DefaultService

func DefaultService(
	repo Repository,
	anchorRepo anchors.AnchorRepository,
	registry *ServiceRegistry,
	idService identity.ServiceDID) Service

DefaultService returns the default implementation of the service

type ServiceRegistry

type ServiceRegistry struct {
	// contains filtered or unexported fields
}

ServiceRegistry matches for a provided coreDocument the corresponding service

func NewServiceRegistry

func NewServiceRegistry() *ServiceRegistry

NewServiceRegistry returns a new instance of service registry

func (*ServiceRegistry) LocateService

func (s *ServiceRegistry) LocateService(serviceID string) (Service, error)

LocateService will return the registered service for the embedded document type

func (*ServiceRegistry) Register

func (s *ServiceRegistry) Register(serviceID string, service Service) error

Register can register a service which implements the ModelDeriver interface

type TokenRegistry

type TokenRegistry interface {
	// OwnerOf to retrieve owner of the tokenID
	OwnerOf(registry common.Address, tokenID []byte) (common.Address, error)

	// CurrentIndexOfToken get the current index of the token
	CurrentIndexOfToken(registry common.Address, tokenID []byte) (*big.Int, error)
}

TokenRegistry defines NFT related functions.

type TreeProof

type TreeProof struct {
	// contains filtered or unexported fields
}

TreeProof is a helper structure to pass to create proofs

type Validator

type Validator interface {
	// Validate validates the updates to the model in newState.
	Validate(oldState Model, newState Model) error
}

Validator is an interface every Validator (atomic or group) should implement

func LatestVersionValidator

func LatestVersionValidator(repo anchors.AnchorRepository) Validator

LatestVersionValidator checks if the document is the latest version

func UpdateVersionValidator

func UpdateVersionValidator() Validator

UpdateVersionValidator validates if the new core document is properly derived from old one

type ValidatorFunc

type ValidatorFunc func(old, new Model) error

ValidatorFunc implements Validator and can be used as a adaptor for functions with specific function signature

func (ValidatorFunc) Validate

func (vf ValidatorFunc) Validate(old, new Model) error

Validate passes the arguments to the underlying validator function and returns the results

type ValidatorGroup

type ValidatorGroup []Validator

ValidatorGroup implements Validator for validating a set of validators.

func PostAnchoredValidator

func PostAnchoredValidator(idService identity.ServiceDID, repo anchors.AnchorRepository) ValidatorGroup

PostAnchoredValidator is a validator group with following validators PreAnchorValidator anchoredValidator should be called after anchoring the document/when received anchored document

func PreAnchorValidator

func PreAnchorValidator(idService identity.ServiceDID) ValidatorGroup

PreAnchorValidator is a validator group with following validators base validator signing root validator document root validator signatures validator should be called before pre anchoring

func ReceivedAnchoredDocumentValidator

func ReceivedAnchoredDocumentValidator(
	idService identity.ServiceDID,
	repo anchors.AnchorRepository,
	collaborator identity.DID) ValidatorGroup

ReceivedAnchoredDocumentValidator is a validator group with following validators transitionValidator PostAnchoredValidator

func RequestDocumentSignatureValidator

func RequestDocumentSignatureValidator(idService identity.ServiceDID, collaborator identity.DID) ValidatorGroup

RequestDocumentSignatureValidator is a validator group with the following validators SignatureValidator transitionsValidator it should be called when a document is received over the p2p layer before signing

func SignatureRequestValidator

func SignatureRequestValidator(sender identity.DID, idService identity.ServiceDID) ValidatorGroup

SignatureRequestValidator returns a validator group with following validators document timestamp for signing validator document author validator base validator signing root validator signatures validator should be used when node receives a document requesting for signature

func SignatureValidator

func SignatureValidator(idService identity.ServiceDID) ValidatorGroup

SignatureValidator is a validator group with following validators baseValidator signingRootValidator signaturesValidator should be called after sender signing the document, before requesting the document and after signature collection

func (ValidatorGroup) Validate

func (group ValidatorGroup) Validate(oldState Model, newState Model) (errs error)

Validate will execute all group specific atomic validations

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL