README
¶
BitXID
BitXID is a DID framework which complys with W3C DID(Decentralized Identifiers) specifications. It has the following features:
- Multiple storage management: BitXID offers both on-chain storage and off-chain storage for DID storage. The best practice will be store small amounts of data(e.g. id, status, etc.) on-chain while store large amounts of data(e.g. public keys, authentication methods, etc.) off-chain(e.g. IPFS), and combines them by store hash of the data on-chain.
- Multiple methods management: not only can BitXID be used to build digital identity for a blockchain but also it can be to build digital identity ecosystem for a blockchain network(i.e. cross-chain platform).
Installation
Install bitxid
package:
go get -u github.com/meshplus/bitxid
import it in your code:
import "github.com/meshplus/bitxid"
Example
BitXID is already used by several great projects, among which BitXHub is one of them. BitXHub DID has already registered on DIF Universal Resolver. You can find BitXHub DID Implementation here and the design of BitXHub DID in the latest BitXHub WhitePaper.
Usage
Usage guide documantation can be found in here.
Contact
Email: bitxhub@hyperchain.cn
Wechat: If you‘re interested in BitXID or BitXHub, please add the assistant to join our community group.
License
BitXID is under the APACHE LICENSE VERSION 2.0.
Documentation
¶
Index ¶
- func Marshal(s interface{}) ([]byte, error)
- func MarshalAccountDoc(docStruct AccountDoc) ([]byte, error)
- func MarshalChainDoc(docStruct ChainDoc) ([]byte, error)
- func Unmarshal(b []byte, s interface{}) error
- func WithAccountDocStorage(ds storage.Storage) func(*AccountDIDRegistry)
- func WithAdmin(a DID) func(*ChainDIDRegistry)
- func WithChainDocStorage(ds storage.Storage) func(*ChainDIDRegistry)
- func WithDIDAdmin(a DID) func(*AccountDIDRegistry)
- func WithGenesisAccountDocContent(doc Doc) func(*AccountDIDRegistry)
- func WithGenesisAccountDocInfo(DocInfo DocInfo) func(*AccountDIDRegistry)
- func WithGenesisChainDocContent(doc Doc) func(*ChainDIDRegistry)
- func WithGenesisChainDocInfo(docInfo DocInfo) func(*ChainDIDRegistry)
- type AccountDIDManager
- type AccountDIDRegistry
- func (r *AccountDIDRegistry) AddAdmin(caller DID) error
- func (r *AccountDIDRegistry) Delete(did DID) error
- func (r *AccountDIDRegistry) Freeze(did DID) error
- func (r *AccountDIDRegistry) GetAdmins() []DID
- func (r *AccountDIDRegistry) GetChainDID() DID
- func (r *AccountDIDRegistry) GetSelfID() DID
- func (r *AccountDIDRegistry) HasAccountDID(did DID) bool
- func (r *AccountDIDRegistry) HasAdmin(caller DID) bool
- func (r *AccountDIDRegistry) Register(accountDID DID, addr string, hash []byte) (string, []byte, error)
- func (r *AccountDIDRegistry) RegisterWithDoc(doc Doc) (string, []byte, error)
- func (r *AccountDIDRegistry) RemoveAdmin(caller DID) error
- func (r *AccountDIDRegistry) Resolve(did DID) (*AccountItem, *AccountDoc, bool, error)
- func (r *AccountDIDRegistry) SetupGenesis() error
- func (r *AccountDIDRegistry) UnFreeze(did DID) error
- func (r *AccountDIDRegistry) Update(accountDID DID, addr string, hash []byte) (string, []byte, error)
- func (r *AccountDIDRegistry) UpdateWithDoc(doc Doc) (string, []byte, error)
- type AccountDoc
- type AccountItem
- type Auth
- type BasicDoc
- type BasicItem
- type BasicManager
- type ChainDIDManager
- type ChainDIDRegistry
- func (r *ChainDIDRegistry) AddAdmin(caller DID) error
- func (r *ChainDIDRegistry) Apply(caller DID, chainDID DID) error
- func (r *ChainDIDRegistry) Audit(chainDID DID, status StatusType) error
- func (r *ChainDIDRegistry) AuditApply(chainDID DID, result bool) error
- func (r *ChainDIDRegistry) Delete(chainDID DID) error
- func (r *ChainDIDRegistry) Freeze(chainDID DID) error
- func (r *ChainDIDRegistry) GetAdmins() []DID
- func (r *ChainDIDRegistry) GetSelfID() DID
- func (r *ChainDIDRegistry) HasAdmin(caller DID) bool
- func (r *ChainDIDRegistry) HasChainDID(chainDID DID) bool
- func (r *ChainDIDRegistry) Register(chainDID DID, addr string, hash []byte) (string, []byte, error)
- func (r *ChainDIDRegistry) RegisterWithDoc(doc Doc) (string, []byte, error)
- func (r *ChainDIDRegistry) RemoveAdmin(caller DID) error
- func (r *ChainDIDRegistry) Resolve(chainDID DID) (*ChainItem, *ChainDoc, bool, error)
- func (r *ChainDIDRegistry) SetupGenesis() error
- func (r *ChainDIDRegistry) Synchronize(item TableItem) error
- func (r *ChainDIDRegistry) UnFreeze(chainDID DID) error
- func (r *ChainDIDRegistry) Update(chainDID DID, addr string, hash []byte) (string, []byte, error)
- func (r *ChainDIDRegistry) UpdateWithDoc(doc Doc) (string, []byte, error)
- type ChainDoc
- type ChainItem
- type ClaimTyp
- type Credential
- type DID
- type DIDType
- type Doc
- type DocDB
- type DocInfo
- type FieldTyp
- type KVDocDB
- type KVTable
- type KeyType
- type PubKey
- type RegistryMode
- type RegistryTable
- type Sig
- type StatusType
- type TableItem
- type VCManager
- type VCRegistry
- func (vcr *VCRegistry) CreateClaimTyp(ct *ClaimTyp) (string, error)
- func (vcr *VCRegistry) DeleteClaimtyp(ctid string)
- func (vcr *VCRegistry) DeleteVC(cid string)
- func (vcr *VCRegistry) GetAllClaimTyps() ([]*ClaimTyp, error)
- func (vcr *VCRegistry) GetClaimTyp(ctid string) (*ClaimTyp, error)
- func (vcr *VCRegistry) GetVC(cid string) (*Credential, error)
- func (vcr *VCRegistry) StoreVC(c *Credential) (string, error)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func MarshalAccountDoc ¶
func MarshalAccountDoc(docStruct AccountDoc) ([]byte, error)
MarshalAccountDoc converts struct doc to byte doc
func MarshalChainDoc ¶
MarshalChainDoc converts struct doc to byte doc
func WithAccountDocStorage ¶
func WithAccountDocStorage(ds storage.Storage) func(*AccountDIDRegistry)
WithAccountDocStorage used for InternalDocDB mode
func WithChainDocStorage ¶
func WithChainDocStorage(ds storage.Storage) func(*ChainDIDRegistry)
WithChainDocStorage used for InternalDocDB mode
func WithDIDAdmin ¶
func WithDIDAdmin(a DID) func(*AccountDIDRegistry)
WithDIDAdmin used for admin setup
func WithGenesisAccountDocContent ¶
func WithGenesisAccountDocContent(doc Doc) func(*AccountDIDRegistry)
WithGenesisAccountDoc used for genesis account doc setup
func WithGenesisAccountDocInfo ¶
func WithGenesisAccountDocInfo(DocInfo DocInfo) func(*AccountDIDRegistry)
WithGenesisAccountDoc used for genesis account doc setup
func WithGenesisChainDocContent ¶
func WithGenesisChainDocContent(doc Doc) func(*ChainDIDRegistry)
WithGenesisChainDoc used for genesis chain doc setup
func WithGenesisChainDocInfo ¶
func WithGenesisChainDocInfo(docInfo DocInfo) func(*ChainDIDRegistry)
WithGenesisChainDoc used for genesis chain doc setup
Types ¶
type AccountDIDManager ¶
type AccountDIDManager interface { BasicManager GetChainDID() DID HasAccountDID(did DID) bool Register(did DID, addr string, hash []byte) (string, []byte, error) RegisterWithDoc(doc Doc) (string, []byte, error) Update(did DID, addr string, hash []byte) (string, []byte, error) UpdateWithDoc(doc Doc) (string, []byte, error) Freeze(did DID) error UnFreeze(did DID) error Delete(did DID) error Resolve(did DID) (*AccountItem, *AccountDoc, bool, error) }
AccountDIDManager represents account did management registry
type AccountDIDRegistry ¶
type AccountDIDRegistry struct { Mode RegistryMode `json:"mode"` SelfChainDID DID `json:"method"` // method of the registry Admins []DID `json:"admins"` // admins of the registry Table RegistryTable `json:"table"` Docdb DocDB `json:"docdb"` GenesisAccountDID DID `json:"genesis_account_did"` GenesisAccountDocInfo DocInfo `json:"genesis_account_doc_info"` GenesisAccountDocContent Doc `json:"genesis_account_doc_content"` // contains filtered or unexported fields }
AccountDIDRegistry for DID Identifier, Every appchain should use this DID Registry module.
func NewAccountDIDRegistry ¶
func NewAccountDIDRegistry( ts storage.Storage, l logrus.FieldLogger, options ...func(*AccountDIDRegistry)) (*AccountDIDRegistry, error)
NewAccountDIDRegistry news a AccountDIDRegistry
func (*AccountDIDRegistry) AddAdmin ¶
func (r *AccountDIDRegistry) AddAdmin(caller DID) error
AddAdmin adds an admin for the registry
func (*AccountDIDRegistry) Delete ¶
func (r *AccountDIDRegistry) Delete(did DID) error
Delete deletes data of an account did
func (*AccountDIDRegistry) Freeze ¶
func (r *AccountDIDRegistry) Freeze(did DID) error
Freeze freezes an account did ATN: only admin should call this.
func (*AccountDIDRegistry) GetAdmins ¶
func (r *AccountDIDRegistry) GetAdmins() []DID
GetAdmins gets admin list of the registry
func (*AccountDIDRegistry) GetChainDID ¶
func (r *AccountDIDRegistry) GetChainDID() DID
GetChainDID get chain did of the registry
func (*AccountDIDRegistry) GetSelfID ¶
func (r *AccountDIDRegistry) GetSelfID() DID
GetSelfID gets genesis did of the registry
func (*AccountDIDRegistry) HasAccountDID ¶
func (r *AccountDIDRegistry) HasAccountDID(did DID) bool
HasAccountDID checks whether an account did exists
func (*AccountDIDRegistry) HasAdmin ¶
func (r *AccountDIDRegistry) HasAdmin(caller DID) bool
HasAdmin checks whether caller is an admin of the registry
func (*AccountDIDRegistry) Register ¶
func (r *AccountDIDRegistry) Register(accountDID DID, addr string, hash []byte) (string, []byte, error)
Register ties did name to a did doc ATN: only did who owns did-name should call this
func (*AccountDIDRegistry) RegisterWithDoc ¶
func (r *AccountDIDRegistry) RegisterWithDoc(doc Doc) (string, []byte, error)
RegisterWithDoc registers with doc
func (*AccountDIDRegistry) RemoveAdmin ¶
func (r *AccountDIDRegistry) RemoveAdmin(caller DID) error
RemoveAdmin removes an admin for the registry
func (*AccountDIDRegistry) Resolve ¶
func (r *AccountDIDRegistry) Resolve(did DID) (*AccountItem, *AccountDoc, bool, error)
Resolve looks up local-chain to resolve did. @*AccountDoc returns nil if mode is ExternalDocDB
func (*AccountDIDRegistry) SetupGenesis ¶
func (r *AccountDIDRegistry) SetupGenesis() error
SetupGenesis set up genesis to boot the whole did registry
func (*AccountDIDRegistry) UnFreeze ¶
func (r *AccountDIDRegistry) UnFreeze(did DID) error
UnFreeze unfreezes an account did ATN: only admin should call this.
func (*AccountDIDRegistry) Update ¶
func (r *AccountDIDRegistry) Update(accountDID DID, addr string, hash []byte) (string, []byte, error)
Update updates data of an account did ATN: only caller who owns did should call this
func (*AccountDIDRegistry) UpdateWithDoc ¶
func (r *AccountDIDRegistry) UpdateWithDoc(doc Doc) (string, []byte, error)
UpdateWithDoc updates with doc
type AccountDoc ¶
AccountDoc represents account identity information
func UnmarshalAccountDoc ¶
func UnmarshalAccountDoc(docBytes []byte) (AccountDoc, error)
UnmarshalAccountDoc converts byte doc to struct doc
func (*AccountDoc) IsValidFormat ¶
func (dd *AccountDoc) IsValidFormat() bool
IsValidFormat checks whether account doc is valid format
func (*AccountDoc) Marshal ¶
func (dd *AccountDoc) Marshal() ([]byte, error)
Marshal marshals account doc
func (*AccountDoc) Unmarshal ¶
func (dd *AccountDoc) Unmarshal(docBytes []byte) error
Unmarshal unmarshals account doc
type AccountItem ¶
type AccountItem struct {
BasicItem
}
AccountItem reperesentis a did item, element of registry table. Registry table is used together with docdb.
func (*AccountItem) Marshal ¶
func (di *AccountItem) Marshal() ([]byte, error)
Marshal marshals account item
func (*AccountItem) Unmarshal ¶
func (di *AccountItem) Unmarshal(docBytes []byte) error
Unmarshal unmarshals account item
type Auth ¶
type Auth struct { PublicKey []string `json:"publicKey"` // ID of PublicKey Strategy string `json:"strategy"` // strategy of publicKey combination }
Auth represents authentication information
type BasicDoc ¶
type BasicDoc struct { ID DID `json:"id"` Type int `json:"type"` Created uint64 `json:"created"` Updated uint64 `json:"updated"` Controller DID `json:"controller"` PublicKey []PubKey `json:"publicKey"` Authentication []Auth `json:"authentication"` }
BasicDoc is the fundamental part of doc structure
type BasicItem ¶
type BasicItem struct { ID DID DocAddr string // addr where the doc file stored DocHash []byte // hash of the doc file Status StatusType // status of the item }
BasicItem is the fundamental part of item structure
type BasicManager ¶
type BasicManager interface { SetupGenesis() error GetSelfID() DID GetAdmins() []DID AddAdmin(caller DID) error RemoveAdmin(caller DID) error HasAdmin(caller DID) bool }
BasicManager represents basic did management that should be used by other type of did management registry.
type ChainDIDManager ¶
type ChainDIDManager interface { BasicManager HasChainDID(chainDID DID) bool Apply(caller DID, chainDID DID) error AuditApply(chainDID DID, result bool) error Audit(chainDID DID, status StatusType) error Register(chainDID DID, addr string, hash []byte) (string, []byte, error) RegisterWithDoc(doc Doc) (string, []byte, error) Update(chainDID DID, addr string, hash []byte) (string, []byte, error) UpdateWithDoc(doc Doc) (string, []byte, error) Freeze(chainDID DID) error UnFreeze(chainDID DID) error Resolve(chainDID DID) (*ChainItem, *ChainDoc, bool, error) Delete(chainDID DID) error }
ChainDIDManager represents chain did management registry
type ChainDIDRegistry ¶
type ChainDIDRegistry struct { Mode RegistryMode `json:"mode"` IsRoot bool `json:"is_root"` Admins []DID `json:"admins"` Table RegistryTable `json:"table"` Docdb DocDB `json:"docdb"` GenesisChainDID DID `json:"genesis_chain_did"` GenesisChainDocInfo DocInfo `json:"genesis_chain_doc_info"` GenesisChainDocContent Doc `json:"genesis_chain_doc_content"` // contains filtered or unexported fields }
ChainDIDRegistry .
func NewChainDIDRegistry ¶
func NewChainDIDRegistry( ts storage.Storage, l logrus.FieldLogger, options ...func(*ChainDIDRegistry)) (*ChainDIDRegistry, error)
NewChainDIDRegistry news a ChainDIDRegistry
func (*ChainDIDRegistry) AddAdmin ¶
func (r *ChainDIDRegistry) AddAdmin(caller DID) error
AddAdmin adds an admin for the registry
func (*ChainDIDRegistry) Apply ¶
func (r *ChainDIDRegistry) Apply(caller DID, chainDID DID) error
Apply apply for rights of a new methd-name
func (*ChainDIDRegistry) Audit ¶
func (r *ChainDIDRegistry) Audit(chainDID DID, status StatusType) error
Audit audits status of a chain did ATN: only admin should call this.
func (*ChainDIDRegistry) AuditApply ¶
func (r *ChainDIDRegistry) AuditApply(chainDID DID, result bool) error
AuditApply audits status of a chain did application ATNS: only admin should call this.
func (*ChainDIDRegistry) Delete ¶
func (r *ChainDIDRegistry) Delete(chainDID DID) error
Delete deletes data of a chain did
func (*ChainDIDRegistry) Freeze ¶
func (r *ChainDIDRegistry) Freeze(chainDID DID) error
Freeze freezes a chain did ATN: only admdin should call this.
func (*ChainDIDRegistry) GetAdmins ¶
func (r *ChainDIDRegistry) GetAdmins() []DID
GetAdmins gets admin list of the registry
func (*ChainDIDRegistry) GetSelfID ¶
func (r *ChainDIDRegistry) GetSelfID() DID
GetSelfID gets genesis did of the registry
func (*ChainDIDRegistry) HasAdmin ¶
func (r *ChainDIDRegistry) HasAdmin(caller DID) bool
HasAdmin checks whether caller is an admin of the registry
func (*ChainDIDRegistry) HasChainDID ¶
func (r *ChainDIDRegistry) HasChainDID(chainDID DID) bool
HasChainDID checks whether a chain did exists
func (*ChainDIDRegistry) Register ¶
Register ties chain did to a chain doc ATN: only did who owns method-name should call this
func (*ChainDIDRegistry) RegisterWithDoc ¶
func (r *ChainDIDRegistry) RegisterWithDoc(doc Doc) (string, []byte, error)
RegisterWithDoc registers with doc
func (*ChainDIDRegistry) RemoveAdmin ¶
func (r *ChainDIDRegistry) RemoveAdmin(caller DID) error
RemoveAdmin removes an admin for the registry
func (*ChainDIDRegistry) Resolve ¶
Resolve looks up local-chain to resolve chain did. @*ChainDoc returns nil if mode is ExternalDocDB
func (*ChainDIDRegistry) SetupGenesis ¶
func (r *ChainDIDRegistry) SetupGenesis() error
SetupGenesis set up genesis to boot the whole methed system
func (*ChainDIDRegistry) Synchronize ¶
func (r *ChainDIDRegistry) Synchronize(item TableItem) error
Synchronize synchronizes table data between different registrys
func (*ChainDIDRegistry) UnFreeze ¶
func (r *ChainDIDRegistry) UnFreeze(chainDID DID) error
UnFreeze unfreezes a chain did ATN: only admdin should call this.
func (*ChainDIDRegistry) Update ¶
Update updates data about a chain did ATN: only did who owns method-name should call this.
func (*ChainDIDRegistry) UpdateWithDoc ¶
func (r *ChainDIDRegistry) UpdateWithDoc(doc Doc) (string, []byte, error)
UpdateWithDoc updates with doc
type ChainDoc ¶
ChainDoc represents chain identity information
func UnmarshalChainDoc ¶
UnmarshalChainDoc converts byte doc to struct doc
func (*ChainDoc) IsValidFormat ¶
IsValidFormat checks whether chain doc is valid format
type ChainItem ¶
type ChainItem struct { BasicItem Owner DID // owner of the chain did, is a did, TODO: owner ==> owners }
ChainItem reperesents a chain did item, element of registry table, it stores all data about a did. Registry table is used together with docdb.
type ClaimTyp ¶
type ClaimTyp struct { ID string `json:"id"` // the universal id of claim type Content []*FieldTyp `json:"content"` }
ClaimTyp represents claim type
type Credential ¶
type Credential struct { ID string `json:"id"` Typ string `json:"typ"` Issuer DID `json:"issuer"` Issued uint64 `json:"issued"` Expiration uint64 `json:"expiration"` Claim string `json:"claim"` // jsonSchema string Signature Sig `json:"signature"` }
Credential represents verifiable credential
func (*Credential) Marshal ¶
func (c *Credential) Marshal() ([]byte, error)
Marshal marshals credential
func (*Credential) Unmarshal ¶
func (c *Credential) Unmarshal(docBytes []byte) error
Unmarshal unmarshals credential
type DID ¶
type DID string
DID represents decentrilzed identifier and method names example identifier: did:bitxhub:appchain001 example method name:
func (DID) GetAddress ¶
GetAddress get address from did-format string
func (DID) GetRootMethod ¶
GetRootMethod get root method from did-format string
func (DID) GetSubMethod ¶
GetSubMethod get sub method from did-format string
func (DID) IsValidFormat ¶
IsValidFormat checks whether did is valid format
type Doc ¶
type Doc interface { Marshal() ([]byte, error) Unmarshal(docBytes []byte) error GetID() DID IsValidFormat() bool GetType() int }
Doc represents did doc
type DocDB ¶
type DocDB interface { Create(doc Doc) (string, error) Update(doc Doc) (string, error) Get(did DID, typ DIDType) (Doc, error) Delete(did DID) Has(did DID) bool Close() error }
DocDB represents did Doc db (used under InternalDocDB mode)
type FieldTyp ¶
type FieldTyp struct { Field string `json:"field"` // field name Typ string `json:"typ"` // field type e.g. int, float, string }
FieldTyp represents field type
type KVTable ¶
KVTable .
func (*KVTable) CreateItem ¶
CreateItem checks and sets
func (*KVTable) UpdateItem ¶
UpdateItem checks and sets
type PubKey ¶
type PubKey struct { ID string `json:"id"` Type string `json:"type"` PublicKeyPem string `json:"publicKeyPem"` }
PubKey represents publick key
type RegistryMode ¶
type RegistryMode int
RegistryMode .
const ( ExternalDocDB RegistryMode = iota InternalDocDB )
type of RegistryMode: @ExternalDocDB: Doc store won't be mastered by Registry @InternalDocDB: Doc store will be mastered by Registry
type RegistryTable ¶
type RegistryTable interface { CreateItem(item TableItem) error UpdateItem(item TableItem) error GetItem(did DID, typ DIDType) (TableItem, error) HasItem(did DID) bool DeleteItem(did DID) Close() error }
RegistryTable represents state table of a registry
type StatusType ¶
type StatusType string
StatusType .
const ( BadStatus StatusType = "BadStatus" Initial StatusType = "Initial" ApplyAudit StatusType = "ApplyAudit" ApplyFailed StatusType = "ApplyFailed" ApplySuccess StatusType = "ApplySuccess" RegisterAudit StatusType = "RegisterAudit" RegisterFailed StatusType = "RegisterFailed" UpdateAudit StatusType = "UpdateAudit" UpdateFailed StatusType = "UpdateFailed" Frozen StatusType = "Frozen" Normal StatusType = "Normal" )
the rule of status code: @BadStatus: something went wrong during get status @Normal: AuditSuccess or Unfrozen
type TableItem ¶
type TableItem interface { Marshal() ([]byte, error) Unmarshal(itemBytes []byte) error GetID() DID }
TableItem represents the table item of a registry table
type VCManager ¶
type VCManager interface { CreateClaimTyp(ct *ClaimTyp) (string, error) GetClaimTyp(ctid string) (*ClaimTyp, error) DeleteClaimtyp(ctid string) GetAllClaimTyps() ([]*ClaimTyp, error) StoreVC(c *Credential) (string, error) GetVC(cid string) (*Credential, error) DeleteVC(cid string) }
VCManager interface for verifiable credential management registry
type VCRegistry ¶
VCRegistry represents verifiable credential management registry
func NewVCRegistry ¶
func NewVCRegistry(s storage.Storage) (*VCRegistry, error)
NewVCRegistry news a NewVCRegistry
func (*VCRegistry) CreateClaimTyp ¶
func (vcr *VCRegistry) CreateClaimTyp(ct *ClaimTyp) (string, error)
CreateClaimTyp creates new claim type
func (*VCRegistry) DeleteClaimtyp ¶
func (vcr *VCRegistry) DeleteClaimtyp(ctid string)
DeleteClaimtyp deletes a claim type
func (*VCRegistry) GetAllClaimTyps ¶
func (vcr *VCRegistry) GetAllClaimTyps() ([]*ClaimTyp, error)
GetAllClaimTyps gets all claim types
func (*VCRegistry) GetClaimTyp ¶
func (vcr *VCRegistry) GetClaimTyp(ctid string) (*ClaimTyp, error)
GetClaimTyp gets a claim type
func (*VCRegistry) GetVC ¶
func (vcr *VCRegistry) GetVC(cid string) (*Credential, error)
GetVC gets a vc
func (*VCRegistry) StoreVC ¶
func (vcr *VCRegistry) StoreVC(c *Credential) (string, error)
StoreVC stores a vc