Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom registration #457

Merged
merged 10 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions chain.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
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 {
if chainID == nil {
return nil
}

k := fmt.Sprintf("%s:%s", blockchain, network)
if _, ok := chainIDs[k]; ok {
return fmt.Errorf("chainID %s:%s already registered", blockchain, network)
}
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
}
122 changes: 120 additions & 2 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,6 +72,24 @@ 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
}

// NetworkID is method specific network identifier
type NetworkID string

Expand All @@ -80,13 +114,48 @@ const (
NoNetwork NetworkID = ""
)

var networks = map[NetworkID]NetworkID{
Main: Main,
Mumbai: Mumbai,
Goerli: Goerli,
Sepolia: Sepolia,
Test: Test,
UnknownNetwork: UnknownNetwork,
}
OBrezhniev marked this conversation as resolved.
Show resolved Hide resolved

// 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
}

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

// RegisterDIDMethodWithByte registers new DID method with byte flag
func RegisterDIDMethodWithByte(m DIDMethod, b *byte) error {
didMethods[m] = m

if b == nil {
return nil
}

if _, ok := DIDMethodByte[m]; ok {
return fmt.Errorf("DID method %s already registered", 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 +195,52 @@ var DIDMethodNetwork = map[DIDMethod]map[DIDNetworkFlag]byte{
},
}

// DIDMethodNetworkOpts is a structure to represent DID method network options
type DIDMethodNetworkOpts struct {
Kolezhniuk marked this conversation as resolved.
Show resolved Hide resolved
Method DIDMethod
MethodByte *byte
Blockchain Blockchain
Network NetworkID
NetworkFlag byte
ChainID *int
}

// RegisterDIDMethodNetwork registers new DID method network
func RegisterDIDMethodNetwork(opts DIDMethodNetworkOpts) error {

b := opts.Blockchain
n := opts.Network
m := opts.Method
blockchains[b] = b
networks[n] = n

err := RegisterDIDMethodWithByte(m, opts.MethodByte)
Kolezhniuk marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return err
}

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

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

err = RegisterChainID(b, n, opts.ChainID)
Kolezhniuk marked this conversation as resolved.
Show resolved Hide resolved

if err != nil {
return err
}

if _, ok := DIDMethodNetwork[m][flg]; ok {
return fmt.Errorf("DID method network %s with blockchain %s and network %s already registered",
m, b, n)
}

DIDMethodNetwork[m][flg] = opts.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 +333,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
125 changes: 125 additions & 0 deletions did_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -379,3 +379,128 @@ func ethAddrFromHex(ea string) [20]byte {
copy(ethAddr[:], eaBytes)
return ethAddr
}

func intPtr(i int) *int {
return &i
}
func bPtr(i byte) *byte {
return &i
}
func strPtr(s string) *string {
return &s
}
Kolezhniuk marked this conversation as resolved.
Show resolved Hide resolved
func TestDID_Custom_Parse_DID(t *testing.T) {
testCases := []struct {
Description string
Data DIDMethodNetworkOpts
ErrorMsg *string
}{
{
Description: "register new did method network",
Data: DIDMethodNetworkOpts{
Method: "test_method",
Blockchain: "test_chain",
Network: "test_net",
ChainID: intPtr(101),
MethodByte: bPtr(0b00000011),
NetworkFlag: 0b0001_0001,
},
},
{
Description: "register one more new did method network",
Data: DIDMethodNetworkOpts{
Method: "method",
Blockchain: "chain",
Network: "network",
ChainID: intPtr(102),
MethodByte: bPtr(0b00000100),
NetworkFlag: 0b0001_0001,
},
},
{
Description: "register network to existing did method",
Data: DIDMethodNetworkOpts{
Method: DIDMethodIden3,
Blockchain: "chain",
Network: Test,
ChainID: intPtr(103),
NetworkFlag: 0b01000000 | 0b00000011,
},
},
{
Description: "register one more network to existing did method",
Data: DIDMethodNetworkOpts{
Method: DIDMethodIden3,
Blockchain: ReadOnly,
Network: "network",
ChainID: intPtr(104),
NetworkFlag: 0b01000000 | 0b00000011,
},
},
{
Description: "register already registered did method network",
Data: DIDMethodNetworkOpts{
Method: DIDMethodIden3,
Blockchain: ReadOnly,
Network: "network",
NetworkFlag: 0b01000000 | 0b00000011,
},
ErrorMsg: strPtr("DID method network iden3 with blockchain readonly and network network already registered"),
},
{
Description: "register exited chain",
Data: DIDMethodNetworkOpts{
Method: DIDMethodIden3,
Blockchain: ReadOnly,
Network: "network",
ChainID: intPtr(104),
NetworkFlag: 0b01000000 | 0b00000011,
},
ErrorMsg: strPtr("chainID readonly:network already registered"),
},
{
Description: "register known chain id to new did method",
Data: DIDMethodNetworkOpts{
Method: "method2",
Blockchain: Polygon,
Network: Mumbai,
MethodByte: bPtr(0b0000_0101),
NetworkFlag: 0b0001_0001,
},
},
}

for _, tc := range testCases {
t.Run(tc.Description, func(t *testing.T) {
err := RegisterDIDMethodNetwork(tc.Data)
if tc.ErrorMsg != nil {
require.EqualError(t, err, *tc.ErrorMsg)
return
}
require.NoError(t, err)
})
}

d := helperBuildDIDFromType(t, "method", "chain", "network")
require.Equal(t, "4bb86obLkMrifHixMY62WM4iQQVr7u29cxWjMAinrT", d.IDStrings[2])

did3, err := w3c.ParseDID("did:method:chain:network:4bb86obLkMrifHixMY62WM4iQQVr7u29cxWjMAinrT")
require.NoError(t, err)

id, err := idFromDID(*did3)
require.NoError(t, err)

require.Equal(t, "4bb86obLkMrifHixMY62WM4iQQVr7u29cxWjMAinrT", id.String())
method, err := MethodFromID(id)
require.NoError(t, err)
require.Equal(t, DIDMethod("method"), method)

blockchain, err := BlockchainFromID(id)
require.NoError(t, err)
require.Equal(t, Blockchain("chain"), blockchain)

networkID, err := NetworkIDFromID(id)
require.NoError(t, err)
require.Equal(t, NetworkID("network"), networkID)

}