Skip to content

Commit

Permalink
Custom registration (#457)
Browse files Browse the repository at this point in the history
* Custom registration
  • Loading branch information
Kolezhniuk authored Dec 12, 2023
1 parent 7ea12c5 commit f4fd2e6
Show file tree
Hide file tree
Showing 3 changed files with 411 additions and 6 deletions.
69 changes: 69 additions & 0 deletions chain.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package core

import (
"fmt"

"github.com/iden3/go-iden3-core/v2/w3c"
)

// ChainID is alias for int32 that represents ChainID
type ChainID int32

// ChainIDs Object containing chain IDs for various blockchains and networks.
var chainIDs = map[string]ChainID{
"eth:main": 1,
"eth:goerli": 5,
"eth:sepolia": 11155111,
"polygon:main": 137,
"polygon:mumbai": 80001,
"zkevm:main": 1101,
"zkevm:test": 1442,
}

// ChainIDfromDID returns chain name from w3c.DID
func ChainIDfromDID(did w3c.DID) (ChainID, error) {

id, err := IDFromDID(did)
if err != nil {
return 0, err
}

blockchain, err := BlockchainFromID(id)
if err != nil {
return 0, err
}

networkID, err := NetworkIDFromID(id)
if err != nil {
return 0, err
}

chainID, ok := chainIDs[fmt.Sprintf("%s:%s", blockchain, networkID)]
if !ok {
return 0, fmt.Errorf("chainID not found for %s:%s", blockchain, networkID)
}

return chainID, nil
}

// RegisterChainID registers chainID for blockchain and network
func RegisterChainID(blockchain Blockchain, network NetworkID, chainID int) error {
k := fmt.Sprintf("%s:%s", blockchain, network)
existingChainID, ok := chainIDs[k]
if ok && existingChainID != ChainID(chainID) {
return fmt.Errorf("chainID '%s:%s' already registered with value %d", blockchain, network, existingChainID)
}
chainIDs[k] = ChainID(chainID)

return nil
}

// GetChainID returns chainID for blockchain and network
func GetChainID(blockchain Blockchain, network NetworkID) (ChainID, error) {
k := fmt.Sprintf("%s:%s", blockchain, network)
if _, ok := chainIDs[k]; !ok {
return 0, fmt.Errorf("chainID not registered for %s:%s", blockchain, network)
}

return chainIDs[k], nil
}
176 changes: 170 additions & 6 deletions did.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,22 @@ const (
DIDMethodOther DIDMethod = ""
)

var didMethods = map[DIDMethod]DIDMethod{
DIDMethodIden3: DIDMethodIden3,
DIDMethodPolygonID: DIDMethodPolygonID,
DIDMethodOther: DIDMethodOther,
}

// GetDIDMethod returns DID method by name
func GetDIDMethod(name string) (DIDMethod, error) {

method, ok := didMethods[DIDMethod(name)]
if !ok {
return DIDMethodOther, fmt.Errorf("DID method '%s' not found", name)
}
return method, nil
}

// Blockchain id of the network "eth", "polygon", etc.
type Blockchain string

Expand All @@ -56,37 +72,100 @@ const (
NoChain Blockchain = ""
)

var blockchains = map[Blockchain]Blockchain{
Ethereum: Ethereum,
Polygon: Polygon,
ZkEVM: ZkEVM,
UnknownChain: UnknownChain,
ReadOnly: ReadOnly,
NoChain: NoChain,
}

// GetBlockchain returns blockchain by name
func GetBlockchain(name string) (Blockchain, error) {
blockchain, ok := blockchains[Blockchain(name)]
if !ok {
return UnknownChain, fmt.Errorf("blockchain '%s' not found", name)
}
return blockchain, nil
}

// RegisterBlockchain registers new blockchain
func RegisterBlockchain(b Blockchain) error {
blockchains[b] = b
return nil
}

// NetworkID is method specific network identifier
type NetworkID string

const (
// Main is main network
Main NetworkID = "main"

// Mumbai is polygon mumbai test network
Mumbai NetworkID = "mumbai"

// Goerli is ethereum goerli test network
Goerli NetworkID = "goerli" // goerli
// Sepolia is ethereum Sepolia test network
Sepolia NetworkID = "sepolia"

// Test is test network
Test NetworkID = "test"

// UnknownNetwork is used when it's not possible to retrieve network from identifier
UnknownNetwork NetworkID = "unknown"
// NoNetwork should be used for readonly identity to build readonly flag
NoNetwork NetworkID = ""
)

var networks = map[NetworkID]NetworkID{
Main: Main,
Mumbai: Mumbai,
Goerli: Goerli,
Sepolia: Sepolia,
Test: Test,
UnknownNetwork: UnknownNetwork,
NoNetwork: NoNetwork,
}

// GetNetwork returns network by name
func GetNetwork(name string) (NetworkID, error) {
network, ok := networks[NetworkID(name)]
if !ok {
return UnknownNetwork, fmt.Errorf("network '%s' not found", name)
}
return network, nil
}

// RegisterNetwork registers new network
func RegisterNetwork(n NetworkID) error {
networks[n] = n
return nil
}

// DIDMethodByte did method flag representation
var DIDMethodByte = map[DIDMethod]byte{
DIDMethodIden3: 0b00000001,
DIDMethodPolygonID: 0b00000010,
DIDMethodOther: 0b11111111,
}

// RegisterDIDMethod registers new DID method with byte flag
func RegisterDIDMethod(m DIDMethod, b byte) error {
existingByte, ok := DIDMethodByte[m]
if ok && existingByte != b {
return fmt.Errorf("DID method '%s' already registered with byte %b", m, existingByte)
}

max := DIDMethodByte[DIDMethodOther]
if b >= max {
return fmt.Errorf("Can't register DID method byte: current %b, maximum byte allowed: %b", b, max-1)
}

didMethods[m] = m
DIDMethodByte[m] = b

return nil
}

// DIDNetworkFlag is a structure to represent DID blockchain and network id
type DIDNetworkFlag struct {
Blockchain Blockchain
Expand Down Expand Up @@ -126,6 +205,88 @@ var DIDMethodNetwork = map[DIDMethod]map[DIDNetworkFlag]byte{
},
}

// DIDMethodNetworkParams is a structure to represent DID method network options
type DIDMethodNetworkParams struct {
Method DIDMethod
Blockchain Blockchain
Network NetworkID
NetworkFlag byte
}

type registrationOptions struct {
chainID *int
methodByte *byte
}

// RegistrationOptions is a type for DID method network options
type RegistrationOptions func(params *registrationOptions)

// WithChainID registers new chain ID method with byte flag
func WithChainID(chainID int) RegistrationOptions {
return func(opts *registrationOptions) {
opts.chainID = &chainID
}
}

// WithDIDMethodByte registers new DID method with byte flag
func WithDIDMethodByte(methodByte byte) RegistrationOptions {
return func(opts *registrationOptions) {
opts.methodByte = &methodByte
}
}

// RegisterDIDMethodNetwork registers new DID method network
func RegisterDIDMethodNetwork(params DIDMethodNetworkParams, opts ...RegistrationOptions) error {
var err error
o := registrationOptions{}
for _, opt := range opts {
opt(&o)
}

b := params.Blockchain
n := params.Network
m := params.Method

err = RegisterBlockchain(b)
if err != nil {
return err
}

err = RegisterNetwork(n)
if err != nil {
return err
}

if o.methodByte != nil {
err = RegisterDIDMethod(m, *o.methodByte)
if err != nil {
return err
}
}

flg := DIDNetworkFlag{Blockchain: b, NetworkID: n}

if _, ok := DIDMethodNetwork[m]; !ok {
DIDMethodNetwork[m] = map[DIDNetworkFlag]byte{}
}

if o.chainID != nil {
err = RegisterChainID(b, n, *o.chainID)
if err != nil {
return err
}
}
existedFlag, ok := DIDMethodNetwork[m][flg]
if ok && existedFlag != params.NetworkFlag {
return fmt.Errorf("DID method network '%s' with blockchain '%s' and network '%s' already registered with another flag '%b'",
m, b, n, existedFlag)
}

DIDMethodNetwork[m][flg] = params.NetworkFlag
return nil

}

// BuildDIDType builds bytes type from chain and network
func BuildDIDType(method DIDMethod, blockchain Blockchain,
network NetworkID) ([2]byte, error) {
Expand Down Expand Up @@ -218,8 +379,11 @@ func newIDFromUnsupportedDID(did w3c.DID) ID {
}

func idFromDID(did w3c.DID) (ID, error) {
method := DIDMethod(did.Method)
_, ok := DIDMethodByte[method]
method, ok := didMethods[DIDMethod(did.Method)]
if !ok {
method = DIDMethodOther
}
_, ok = DIDMethodByte[method]
if !ok || method == DIDMethodOther {
return ID{}, ErrMethodUnknown
}
Expand Down
Loading

0 comments on commit f4fd2e6

Please sign in to comment.