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 2 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
2 changes: 1 addition & 1 deletion chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func ChainIDfromDID(did w3c.DID) (ChainID, error) {
func RegisterChainID(blockchain Blockchain, network NetworkID, chainID int) error {

k := fmt.Sprintf("%s:%s", blockchain, network)
if _, ok := chainIDs[k]; ok {
if existingChainID, ok := chainIDs[k]; ok && existingChainID != ChainID(chainID) {
vmidyllic marked this conversation as resolved.
Show resolved Hide resolved
return fmt.Errorf("chainID %s:%s already registered", blockchain, network)
}
chainIDs[k] = ChainID(chainID)
Expand Down
84 changes: 56 additions & 28 deletions did.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func GetDIDMethod(name string) (DIDMethod, error) {

method, ok := didMethods[DIDMethod(name)]
if !ok {
return DIDMethodOther, fmt.Errorf("DID method %s not found", name)
return DIDMethodOther, fmt.Errorf("DID method '%s' not found", name)
}
return method, nil
}
Expand Down Expand Up @@ -85,29 +85,31 @@ var blockchains = map[Blockchain]Blockchain{
func GetBlockchain(name string) (Blockchain, error) {
blockchain, ok := blockchains[Blockchain(name)]
if !ok {
return UnknownChain, fmt.Errorf("blockchain %s not found", name)
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
Expand All @@ -121,32 +123,44 @@ var networks = map[NetworkID]NetworkID{
Sepolia: Sepolia,
Test: Test,
UnknownNetwork: UnknownNetwork,
NoNetwork: NoNetwork,
}
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 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,
}

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

if _, ok := DIDMethodByte[m]; ok {
if existingByte, ok := DIDMethodByte[m]; ok && existingByte != b {
vmidyllic marked this conversation as resolved.
Show resolved Hide resolved
return fmt.Errorf("DID method %s already registered", m)
}

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
Expand Down Expand Up @@ -197,40 +211,54 @@ type DIDMethodNetworkParams struct {
Blockchain Blockchain
Network NetworkID
NetworkFlag byte
chainID *int
methodByte *byte
}

type registrationOptions struct {
chainID *int
methodByte *byte
}

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

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

// WithDIDMethodByte registers new DID method with byte flag
func WithDIDMethodByte(methodByte byte) RegistrationOptions {
return func(params *DIDMethodNetworkParams) {
params.methodByte = &methodByte
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(&params)
opt(&o)
}

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

if params.methodByte != nil {
err := RegisterDIDMethodWithByte(m, *params.methodByte)
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
}
Expand All @@ -242,15 +270,15 @@ func RegisterDIDMethodNetwork(params DIDMethodNetworkParams, opts ...Registratio
DIDMethodNetwork[m] = map[DIDNetworkFlag]byte{}
}

if params.chainID != nil {
err := RegisterChainID(b, n, *params.chainID)
if o.chainID != nil {
err = RegisterChainID(b, n, *o.chainID)
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",
if existed, ok := DIDMethodNetwork[m][flg]; ok && existed != params.NetworkFlag {
return fmt.Errorf("DID method network '%s' with blockchain '%s' and network '%s' already registered",
m, b, n)
}

Expand Down
103 changes: 78 additions & 25 deletions did_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -380,14 +380,10 @@ func ethAddrFromHex(ea string) [20]byte {
return ethAddr
}

func strPtr(s string) *string {
return &s
}
func TestDID_Custom_Parse_DID(t *testing.T) {
func TestCustomDIDRegistration(t *testing.T) {
testCases := []struct {
Description string
Data DIDMethodNetworkParams
ErrorMsg *string
opts []RegistrationOptions
}{
{
Expand All @@ -411,46 +407,44 @@ func TestDID_Custom_Parse_DID(t *testing.T) {
opts: []RegistrationOptions{WithChainID(102), WithDIDMethodByte(0b00000100)},
},
{
Description: "register network to existing did method",
Description: "register the same new did method network",
Data: DIDMethodNetworkParams{
Method: DIDMethodIden3,
Method: "method",
Blockchain: "chain",
Network: Test,
NetworkFlag: 0b01000000 | 0b00000011,
Network: "network",
NetworkFlag: 0b0001_0001,
},
opts: []RegistrationOptions{WithChainID(103)},
opts: []RegistrationOptions{WithChainID(102), WithDIDMethodByte(0b00000100)},
},
{
Description: "register one more network to existing did method",
Description: "register network to existing did method",
Data: DIDMethodNetworkParams{
Method: DIDMethodIden3,
Blockchain: ReadOnly,
Network: "network",
Blockchain: "chain",
Network: Test,
NetworkFlag: 0b01000000 | 0b00000011,
},
opts: []RegistrationOptions{WithChainID(104)},
opts: []RegistrationOptions{WithChainID(103)},
},
{
Description: "register already registered did method network",
Description: "register network to existing did method and chainId",
Data: DIDMethodNetworkParams{
Method: DIDMethodIden3,
Blockchain: ReadOnly,
Network: "network",
NetworkFlag: 0b01000000 | 0b00000011,
Network: NoNetwork,
NetworkFlag: 0b00000000,
},
ErrorMsg: strPtr("DID method network iden3 with blockchain readonly and network network already registered"),
opts: []RegistrationOptions{WithChainID(103)},
},
{
Description: "register exited chain",
Description: "register one more network to existing did method",
Data: DIDMethodNetworkParams{
Method: DIDMethodIden3,
Blockchain: ReadOnly,
Network: "network",
NetworkFlag: 0b01000000 | 0b00000011,
},
opts: []RegistrationOptions{WithChainID(104)},

ErrorMsg: strPtr("chainID readonly:network already registered"),
},
{
Description: "register known chain id to new did method",
Expand All @@ -467,10 +461,6 @@ func TestDID_Custom_Parse_DID(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.Description, func(t *testing.T) {
err := RegisterDIDMethodNetwork(tc.Data, tc.opts...)
if tc.ErrorMsg != nil {
require.EqualError(t, err, *tc.ErrorMsg)
return
}
require.NoError(t, err)
})
}
Expand Down Expand Up @@ -498,3 +488,66 @@ func TestDID_Custom_Parse_DID(t *testing.T) {
require.Equal(t, NetworkID("network"), networkID)

}

func TestCustomDIDRegistration_Negative(t *testing.T) {
testCases := []struct {
Description string
Data DIDMethodNetworkParams
opts []RegistrationOptions
err string
}{

{
Description: "try to overwrite existing chain id",
Data: DIDMethodNetworkParams{
Method: DIDMethodIden3,
Blockchain: Polygon,
Network: Mumbai,
NetworkFlag: 0b0001_0001,
},
opts: []RegistrationOptions{WithChainID(1)},
err: "chainID polygon:mumbai already registered",
},
{
Description: "try to overwrite existing DID method byte",
Data: DIDMethodNetworkParams{
Method: DIDMethodIden3,
Blockchain: Ethereum,
Network: Main,
NetworkFlag: 0b00100000 | 0b00000001,
},
opts: []RegistrationOptions{WithChainID(1), WithDIDMethodByte(0b00000010)},
err: "DID method iden3 already registered",
},
{
Description: "try to write max did method byte",
Data: DIDMethodNetworkParams{
Method: "method33",
Blockchain: Ethereum,
Network: Main,
NetworkFlag: 0b00100000 | 0b00000001,
},
opts: []RegistrationOptions{WithChainID(1), WithDIDMethodByte(0b11111111)},
err: "Can't register DID method byte: current 11111111, maximum byte allowed: 11111110",
},
{
Description: "try to rewrite existing DID Method Network Flag",
Data: DIDMethodNetworkParams{
Method: DIDMethodIden3,
Blockchain: Ethereum,
Network: Main,
NetworkFlag: 0b00100000 | 0b00000011,
},
opts: nil,
err: "DID method network 'iden3' with blockchain 'eth' and network 'main' already registered",
},
}

for _, tc := range testCases {
t.Run(tc.Description, func(t *testing.T) {
err := RegisterDIDMethodNetwork(tc.Data, tc.opts...)
require.EqualError(t, err, tc.err)
})
}

}