From f19524337d2a8ec352c6b6769ccbc0341c28a6d0 Mon Sep 17 00:00:00 2001 From: Dimasik Kolezhniuk Date: Tue, 28 Nov 2023 10:40:51 +0100 Subject: [PATCH 01/10] Custom registration --- did.go | 204 +++++++++++++++++++++++++++++++++++++++++++++++++++- did_test.go | 60 ++++++++++++++++ 2 files changed, 262 insertions(+), 2 deletions(-) diff --git a/did.go b/did.go index 4abece0..126429d 100644 --- a/did.go +++ b/did.go @@ -38,6 +38,32 @@ 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 +} + +// RegisterDIDMethod registers new DID method +func RegisterDIDMethod(method string) error { + m := DIDMethod(method) + if _, ok := didMethods[m]; ok { + return fmt.Errorf("DID method %s already registered", method) + } + didMethods[m] = m + return nil +} + // Blockchain id of the network "eth", "polygon", etc. type Blockchain string @@ -56,6 +82,32 @@ const ( NoChain Blockchain = "" ) +var blockchains = map[Blockchain]Blockchain{ + Ethereum: Ethereum, + Polygon: Polygon, + ZkEVM: ZkEVM, + UnknownChain: UnknownChain, +} + +// 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(blockchain string) error { + b := Blockchain(blockchain) + if _, ok := blockchains[b]; ok { + return fmt.Errorf("blockchain %s already registered", blockchain) + } + blockchains[b] = b + return nil +} + // NetworkID is method specific network identifier type NetworkID string @@ -80,6 +132,34 @@ const ( NoNetwork NetworkID = "" ) +var networks = map[NetworkID]NetworkID{ + Main: Main, + Mumbai: Mumbai, + Goerli: Goerli, + Sepolia: Sepolia, + Test: Test, + UnknownNetwork: UnknownNetwork, +} + +// 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(name string) error { + n := NetworkID(name) + if _, ok := networks[n]; ok { + return fmt.Errorf("network %s already registered", n) + } + networks[n] = n + return nil +} + // DIDMethodByte did method flag representation var DIDMethodByte = map[DIDMethod]byte{ DIDMethodIden3: 0b00000001, @@ -87,6 +167,20 @@ var DIDMethodByte = map[DIDMethod]byte{ DIDMethodOther: 0b11111111, } +// RegisterDIDMethodByte did method network flag representation +func RegisterDIDMethodByte(method DIDMethod, b byte) error { + + if _, ok := didMethods[method]; !ok { + return fmt.Errorf("DID method %s not registered", method) + } + + if _, ok := DIDMethodByte[method]; ok { + return fmt.Errorf("DID method byte %s already registered", method) + } + DIDMethodByte[method] = b + return nil +} + // DIDNetworkFlag is a structure to represent DID blockchain and network id type DIDNetworkFlag struct { Blockchain Blockchain @@ -126,6 +220,109 @@ var DIDMethodNetwork = map[DIDMethod]map[DIDNetworkFlag]byte{ }, } +// RegisterDIDMethodNetwork registers new DID method network +func RegisterDIDMethodNetwork(method DIDMethod, blockchain Blockchain, network NetworkID, b byte) error { + + if _, ok := didMethods[method]; !ok { + return fmt.Errorf("DID method %s not registered", method) + } + + if _, ok := blockchains[blockchain]; !ok { + return fmt.Errorf("blockchain %s not registered", blockchain) + } + + if _, ok := networks[network]; !ok { + return fmt.Errorf("network %s not registered", network) + } + + flg := DIDNetworkFlag{Blockchain: blockchain, NetworkID: network} + if _, ok := DIDMethodNetwork[method][flg]; ok { + return fmt.Errorf("DID method network %s already registered", method) + } + + if _, ok := DIDMethodNetwork[method]; !ok { + DIDMethodNetwork[method] = map[DIDNetworkFlag]byte{} + DIDMethodNetwork[method][flg] = b + return nil + } + + DIDMethodNetwork[method][flg] = b + return nil + +} + +func RegisterDIDMethodNetworkImplicit(method DIDMethod, blockchain Blockchain, network NetworkID) error { + m := DIDMethod(method) + if _, ok := didMethods[m]; !ok { + didMethods[m] = m + } + + b := Blockchain(blockchain) + if _, ok := blockchains[b]; !ok { + blockchains[b] = b + } + + n := NetworkID(network) + if _, ok := networks[n]; !ok { + networks[n] = n + } + + if _, ok := DIDMethodByte[m]; !ok { + preLatest := byte(0b00000000) + for k, v := range DIDMethodByte { + if v > preLatest && k != DIDMethodOther { + preLatest = v + } + } + preLatest++ + + if preLatest >= DIDMethodByte[DIDMethodOther] { + return fmt.Errorf("DID method byte %s already registered", method) + } + DIDMethodByte[m] = preLatest + } + + flg := DIDNetworkFlag{Blockchain: b, NetworkID: n} + + if _, ok := DIDMethodNetwork[m]; !ok { + DIDMethodNetwork[m] = map[DIDNetworkFlag]byte{} + } + + if _, ok := DIDMethodNetwork[m][flg]; ok { + return fmt.Errorf("DID method network %s already registered", method) + } + + flags, _ := DIDMethodNetwork[m] + + if len(flags) == 0 { + DIDMethodNetwork[m][flg] = 0b00010000 | 0b00000001 + return nil + } + // find biggest flag byte + preLatest := byte(0b00000000) + for _, v := range flags { + if v > preLatest { + preLatest = v + } + } + + // split flag byte to 2 parts + chainPart := (preLatest >> 4) + 1 + networkPart := (preLatest & 0b00001111) + 1 + + if chainPart >= 0b1111 { + return fmt.Errorf(`Reached max number of blockchains for did method: %s`, method) + } + + if networkPart >= 0b1111 { + return fmt.Errorf(`Reached max number of networks for did method: %s`, method) + } + + // join parts + DIDMethodNetwork[m][flg] = (chainPart << 4) | networkPart + return nil +} + // BuildDIDType builds bytes type from chain and network func BuildDIDType(method DIDMethod, blockchain Blockchain, network NetworkID) ([2]byte, error) { @@ -218,8 +415,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 } diff --git a/did_test.go b/did_test.go index 8deaa2e..f3b3ed3 100644 --- a/did_test.go +++ b/did_test.go @@ -379,3 +379,63 @@ func ethAddrFromHex(ea string) [20]byte { copy(ethAddr[:], eaBytes) return ethAddr } + +func TestDID_Custom_Parse_DID(t *testing.T) { + net := "test_net" + met := "test_method" + chain := "test_chain" + var err error + err = RegisterBlockchain(chain) + require.NoError(t, err) + err = RegisterNetwork(net) + require.NoError(t, err) + err = RegisterDIDMethod(met) + require.NoError(t, err) + err = RegisterDIDMethodByte(DIDMethod(met), 0b00000011) + require.NoError(t, err) + b, err := GetBlockchain(chain) + require.NoError(t, err) + m, err := GetDIDMethod(met) + require.NoError(t, err) + n, err := GetNetwork(net) + require.NoError(t, err) + err = RegisterDIDMethodNetwork(m, b, n, 0b0001_0001) + require.NoError(t, err) + + err = RegisterDIDMethodNetworkImplicit("method", "chain", "network") + require.NoError(t, err) + + err = RegisterDIDMethodNetworkImplicit(DIDMethodIden3, "chain", "network") + require.NoError(t, err) + + err = RegisterDIDMethodNetworkImplicit(DIDMethodIden3, "chain", Test) + require.NoError(t, err) + + err = RegisterDIDMethodNetworkImplicit(DIDMethodIden3, ReadOnly, "network") + require.NoError(t, err) + + err = RegisterDIDMethodNetworkImplicit(DIDMethodIden3, ReadOnly, Test) + require.NoError(t, err) + + err = RegisterDIDMethodNetworkImplicit("method2", "chain2", "network2") + require.NoError(t, err) + + d := helperBuildDIDFromType(t, "method2", "chain2", "network2") + require.Equal(t, "5UtG9EXvF25j3X5uycwr4uy7Hjhni8bMposv3Lgv8o", d.IDStrings[2]) + + did, err := w3c.ParseDID("did:method:chain:network:4bb86obLkMrifHixMY62WM4iQQVr7u29cxWjMAinrT") + require.NoError(t, err) + id, err := IDFromDID(*did) + 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) +} From 910759df6e1686c2824426f28fa00eb41726c4e0 Mon Sep 17 00:00:00 2001 From: Dimasik Kolezhniuk Date: Tue, 28 Nov 2023 11:28:54 +0100 Subject: [PATCH 02/10] Fix lint --- did.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/did.go b/did.go index 126429d..a28c750 100644 --- a/did.go +++ b/did.go @@ -292,7 +292,7 @@ func RegisterDIDMethodNetworkImplicit(method DIDMethod, blockchain Blockchain, n return fmt.Errorf("DID method network %s already registered", method) } - flags, _ := DIDMethodNetwork[m] + flags := DIDMethodNetwork[m] if len(flags) == 0 { DIDMethodNetwork[m][flg] = 0b00010000 | 0b00000001 From 17766a668da11c465615f4f5703bd872547b7a25 Mon Sep 17 00:00:00 2001 From: Dimasik Kolezhniuk Date: Tue, 28 Nov 2023 15:18:58 +0100 Subject: [PATCH 03/10] Remove implicit flow. Fix test --- did.go | 29 ++++++++++------------- did_test.go | 66 ++++++++++++++++++++++++++++------------------------- 2 files changed, 47 insertions(+), 48 deletions(-) diff --git a/did.go b/did.go index a28c750..823c58b 100644 --- a/did.go +++ b/did.go @@ -54,16 +54,6 @@ func GetDIDMethod(name string) (DIDMethod, error) { return method, nil } -// RegisterDIDMethod registers new DID method -func RegisterDIDMethod(method string) error { - m := DIDMethod(method) - if _, ok := didMethods[m]; ok { - return fmt.Errorf("DID method %s already registered", method) - } - didMethods[m] = m - return nil -} - // Blockchain id of the network "eth", "polygon", etc. type Blockchain string @@ -87,6 +77,8 @@ var blockchains = map[Blockchain]Blockchain{ Polygon: Polygon, ZkEVM: ZkEVM, UnknownChain: UnknownChain, + ReadOnly: ReadOnly, + NoChain: NoChain, } // GetBlockchain returns blockchain by name @@ -167,17 +159,20 @@ var DIDMethodByte = map[DIDMethod]byte{ DIDMethodOther: 0b11111111, } -// RegisterDIDMethodByte did method network flag representation -func RegisterDIDMethodByte(method DIDMethod, b byte) error { +// RegisterDIDMethodWithByte registers new DID method with byte flag +func RegisterDIDMethodWithByte(method string, b byte) error { - if _, ok := didMethods[method]; !ok { - return fmt.Errorf("DID method %s not registered", method) + m := DIDMethod(method) + if _, ok := didMethods[m]; ok { + return fmt.Errorf("DID method %s already registered", method) } - if _, ok := DIDMethodByte[method]; ok { + didMethods[m] = m + if _, ok := DIDMethodByte[m]; ok { return fmt.Errorf("DID method byte %s already registered", method) } - DIDMethodByte[method] = b + DIDMethodByte[m] = b + return nil } @@ -237,7 +232,7 @@ func RegisterDIDMethodNetwork(method DIDMethod, blockchain Blockchain, network N flg := DIDNetworkFlag{Blockchain: blockchain, NetworkID: network} if _, ok := DIDMethodNetwork[method][flg]; ok { - return fmt.Errorf("DID method network %s already registered", method) + return fmt.Errorf("DID method network %s:%s:%s already registered", method, blockchain, network) } if _, ok := DIDMethodNetwork[method]; !ok { diff --git a/did_test.go b/did_test.go index f3b3ed3..de3b911 100644 --- a/did_test.go +++ b/did_test.go @@ -381,61 +381,65 @@ func ethAddrFromHex(ea string) [20]byte { } func TestDID_Custom_Parse_DID(t *testing.T) { - net := "test_net" - met := "test_method" - chain := "test_chain" var err error - err = RegisterBlockchain(chain) + err = RegisterBlockchain("test_chain") require.NoError(t, err) - err = RegisterNetwork(net) + err = RegisterNetwork("test_net") require.NoError(t, err) - err = RegisterDIDMethod(met) + err = RegisterDIDMethodWithByte("test_method", 0b00000011) require.NoError(t, err) - err = RegisterDIDMethodByte(DIDMethod(met), 0b00000011) + err = RegisterDIDMethodNetwork("test_method", "test_chain", "test_net", 0b0001_0001) require.NoError(t, err) - b, err := GetBlockchain(chain) + err = RegisterDIDMethodWithByte("method", 0b0000_0100) require.NoError(t, err) - m, err := GetDIDMethod(met) + err = RegisterBlockchain("chain") require.NoError(t, err) - n, err := GetNetwork(net) - require.NoError(t, err) - err = RegisterDIDMethodNetwork(m, b, n, 0b0001_0001) + err = RegisterNetwork("network") require.NoError(t, err) - err = RegisterDIDMethodNetworkImplicit("method", "chain", "network") + var m DIDMethod + var b Blockchain + var n NetworkID + m, err = GetDIDMethod("method") require.NoError(t, err) - - err = RegisterDIDMethodNetworkImplicit(DIDMethodIden3, "chain", "network") + b, err = GetBlockchain("chain") require.NoError(t, err) - - err = RegisterDIDMethodNetworkImplicit(DIDMethodIden3, "chain", Test) + n, err = GetNetwork("network") require.NoError(t, err) - err = RegisterDIDMethodNetworkImplicit(DIDMethodIden3, ReadOnly, "network") + err = RegisterDIDMethodNetwork(m, b, n, 0b0001_0001) require.NoError(t, err) - - err = RegisterDIDMethodNetworkImplicit(DIDMethodIden3, ReadOnly, Test) + err = RegisterDIDMethodNetwork(DIDMethodIden3, b, Test, 0b01000000|0b00000011) + require.NoError(t, err) + err = RegisterDIDMethodNetwork(DIDMethodIden3, ReadOnly, n, 0b01000000|0b00000011) require.NoError(t, err) - err = RegisterDIDMethodNetworkImplicit("method2", "chain2", "network2") + err = RegisterDIDMethodNetwork(DIDMethodIden3, ReadOnly, n, 0b01010000|0b00000100) + require.EqualError(t, err, "DID method network iden3:readonly:network already registered") + + err = RegisterDIDMethodWithByte("method2", 0b0000_0101) + require.NoError(t, err) + err = RegisterBlockchain("chain2") + require.NoError(t, err) + err = RegisterNetwork("network2") + require.NoError(t, err) + err = RegisterDIDMethodNetwork("method2", "chain2", "network2", 0b0001_0001) require.NoError(t, err) d := helperBuildDIDFromType(t, "method2", "chain2", "network2") - require.Equal(t, "5UtG9EXvF25j3X5uycwr4uy7Hjhni8bMposv3Lgv8o", d.IDStrings[2]) - + require.Equal(t, d.IDStrings[2], "5UtG9EXvF25j3X5uycwr4uy7Hjhni8bMposv3Lgv8o") did, err := w3c.ParseDID("did:method:chain:network:4bb86obLkMrifHixMY62WM4iQQVr7u29cxWjMAinrT") require.NoError(t, err) - id, err := IDFromDID(*did) + id, err := idFromDID(*did) require.NoError(t, err) require.Equal(t, "4bb86obLkMrifHixMY62WM4iQQVr7u29cxWjMAinrT", id.String()) - - method, err := MethodFromID(id) + met, err := MethodFromID(id) require.NoError(t, err) - require.Equal(t, DIDMethod("method"), method) - blockchain, err := BlockchainFromID(id) + require.Equal(t, met, m) + bl, err := BlockchainFromID(id) require.NoError(t, err) - require.Equal(t, Blockchain("chain"), blockchain) - networkID, err := NetworkIDFromID(id) + require.Equal(t, bl, b) + net, err := NetworkIDFromID(id) require.NoError(t, err) - require.Equal(t, NetworkID("network"), networkID) + require.Equal(t, net, n) } From 357f7434efdc113ef851c755896dc94734c35352 Mon Sep 17 00:00:00 2001 From: Dimasik Kolezhniuk Date: Tue, 28 Nov 2023 21:48:30 +0100 Subject: [PATCH 04/10] Move chain id to core --- chain.go | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++ did.go | 78 ++++----------------------------------------------- did_test.go | 15 +++++++++- 3 files changed, 100 insertions(+), 73 deletions(-) create mode 100644 chain.go diff --git a/chain.go b/chain.go new file mode 100644 index 0000000..78ecd7e --- /dev/null +++ b/chain.go @@ -0,0 +1,80 @@ +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": 1, + "eth:main": 1, + "eth:goerli": 5, + "eth:sepolia": 11155111, + "polygon": 137, + "polygon:main": 137, + "polygon:mumbai": 80001, + "zkevm": 1101, + "zkevm:main": 1101, + "zkevm:test": 1442, +} + +// ChainIDfromDID returns chain name from w3c.DID +func ChainIDfromDID(did w3c.DID) (ChainID, error) { + // TODO: fix for networks like eth / polygon / zkevm + + 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 _, ok := blockchains[blockchain]; !ok { + return fmt.Errorf("blockchain not registered: %s", blockchain) + } + + if _, ok := networks[network]; !ok { + return fmt.Errorf("network not registered: %s", network) + } + + k := fmt.Sprintf("%s:%s", blockchain, network) + if _, ok := chainIDs[k]; ok { + return fmt.Errorf("chainID already registered for %s:%s", 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 +} diff --git a/did.go b/did.go index 823c58b..45e1502 100644 --- a/did.go +++ b/did.go @@ -235,6 +235,12 @@ func RegisterDIDMethodNetwork(method DIDMethod, blockchain Blockchain, network N return fmt.Errorf("DID method network %s:%s:%s already registered", method, blockchain, network) } + // check chainID + _, err := GetChainID(blockchain, network) + if err != nil { + return err + } + if _, ok := DIDMethodNetwork[method]; !ok { DIDMethodNetwork[method] = map[DIDNetworkFlag]byte{} DIDMethodNetwork[method][flg] = b @@ -246,78 +252,6 @@ func RegisterDIDMethodNetwork(method DIDMethod, blockchain Blockchain, network N } -func RegisterDIDMethodNetworkImplicit(method DIDMethod, blockchain Blockchain, network NetworkID) error { - m := DIDMethod(method) - if _, ok := didMethods[m]; !ok { - didMethods[m] = m - } - - b := Blockchain(blockchain) - if _, ok := blockchains[b]; !ok { - blockchains[b] = b - } - - n := NetworkID(network) - if _, ok := networks[n]; !ok { - networks[n] = n - } - - if _, ok := DIDMethodByte[m]; !ok { - preLatest := byte(0b00000000) - for k, v := range DIDMethodByte { - if v > preLatest && k != DIDMethodOther { - preLatest = v - } - } - preLatest++ - - if preLatest >= DIDMethodByte[DIDMethodOther] { - return fmt.Errorf("DID method byte %s already registered", method) - } - DIDMethodByte[m] = preLatest - } - - flg := DIDNetworkFlag{Blockchain: b, NetworkID: n} - - if _, ok := DIDMethodNetwork[m]; !ok { - DIDMethodNetwork[m] = map[DIDNetworkFlag]byte{} - } - - if _, ok := DIDMethodNetwork[m][flg]; ok { - return fmt.Errorf("DID method network %s already registered", method) - } - - flags := DIDMethodNetwork[m] - - if len(flags) == 0 { - DIDMethodNetwork[m][flg] = 0b00010000 | 0b00000001 - return nil - } - // find biggest flag byte - preLatest := byte(0b00000000) - for _, v := range flags { - if v > preLatest { - preLatest = v - } - } - - // split flag byte to 2 parts - chainPart := (preLatest >> 4) + 1 - networkPart := (preLatest & 0b00001111) + 1 - - if chainPart >= 0b1111 { - return fmt.Errorf(`Reached max number of blockchains for did method: %s`, method) - } - - if networkPart >= 0b1111 { - return fmt.Errorf(`Reached max number of networks for did method: %s`, method) - } - - // join parts - DIDMethodNetwork[m][flg] = (chainPart << 4) | networkPart - return nil -} - // BuildDIDType builds bytes type from chain and network func BuildDIDType(method DIDMethod, blockchain Blockchain, network NetworkID) ([2]byte, error) { diff --git a/did_test.go b/did_test.go index de3b911..ad6a8fb 100644 --- a/did_test.go +++ b/did_test.go @@ -388,6 +388,8 @@ func TestDID_Custom_Parse_DID(t *testing.T) { require.NoError(t, err) err = RegisterDIDMethodWithByte("test_method", 0b00000011) require.NoError(t, err) + err = RegisterChainID("test_chain", "test_net", 101) + require.NoError(t, err) err = RegisterDIDMethodNetwork("test_method", "test_chain", "test_net", 0b0001_0001) require.NoError(t, err) err = RegisterDIDMethodWithByte("method", 0b0000_0100) @@ -406,11 +408,18 @@ func TestDID_Custom_Parse_DID(t *testing.T) { require.NoError(t, err) n, err = GetNetwork("network") require.NoError(t, err) - + err = RegisterChainID(b, n, 102) + require.NoError(t, err) err = RegisterDIDMethodNetwork(m, b, n, 0b0001_0001) require.NoError(t, err) + + err = RegisterChainID(b, Test, 103) + require.NoError(t, err) + err = RegisterDIDMethodNetwork(DIDMethodIden3, b, Test, 0b01000000|0b00000011) require.NoError(t, err) + err = RegisterChainID(ReadOnly, n, 104) + require.NoError(t, err) err = RegisterDIDMethodNetwork(DIDMethodIden3, ReadOnly, n, 0b01000000|0b00000011) require.NoError(t, err) @@ -423,6 +432,10 @@ func TestDID_Custom_Parse_DID(t *testing.T) { require.NoError(t, err) err = RegisterNetwork("network2") require.NoError(t, err) + + err = RegisterChainID("chain2", "network2", 105) + require.NoError(t, err) + err = RegisterDIDMethodNetwork("method2", "chain2", "network2", 0b0001_0001) require.NoError(t, err) From b20901fdcaa68a6a845ba86faffb0eb5a2d9c1ea Mon Sep 17 00:00:00 2001 From: Dimasik Kolezhniuk Date: Thu, 30 Nov 2023 22:03:51 +0100 Subject: [PATCH 05/10] Update registration methods & test --- chain.go | 18 ++---- did.go | 81 +++++++++++-------------- did_test.go | 172 +++++++++++++++++++++++++++++++++------------------- 3 files changed, 150 insertions(+), 121 deletions(-) diff --git a/chain.go b/chain.go index 78ecd7e..0791ff7 100644 --- a/chain.go +++ b/chain.go @@ -11,21 +11,17 @@ type ChainID int32 // ChainIDs Object containing chain IDs for various blockchains and networks. var chainIDs = map[string]ChainID{ - "eth": 1, "eth:main": 1, "eth:goerli": 5, "eth:sepolia": 11155111, - "polygon": 137, "polygon:main": 137, "polygon:mumbai": 80001, - "zkevm": 1101, "zkevm:main": 1101, "zkevm:test": 1442, } // ChainIDfromDID returns chain name from w3c.DID func ChainIDfromDID(did w3c.DID) (ChainID, error) { - // TODO: fix for networks like eth / polygon / zkevm id, err := IDFromDID(did) if err != nil { @@ -51,20 +47,16 @@ func ChainIDfromDID(did w3c.DID) (ChainID, error) { } // RegisterChainID registers chainID for blockchain and network -func RegisterChainID(blockchain Blockchain, network NetworkID, chainID int) error { - if _, ok := blockchains[blockchain]; !ok { - return fmt.Errorf("blockchain not registered: %s", blockchain) - } - - if _, ok := networks[network]; !ok { - return fmt.Errorf("network not registered: %s", 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 already registered for %s:%s", blockchain, network) + return fmt.Errorf("chainID %s:%s already registered", blockchain, network) } - chainIDs[k] = ChainID(chainID) + chainIDs[k] = ChainID(*chainID) return nil } diff --git a/did.go b/did.go index 45e1502..6cbd4b2 100644 --- a/did.go +++ b/did.go @@ -90,16 +90,6 @@ func GetBlockchain(name string) (Blockchain, error) { return blockchain, nil } -// RegisterBlockchain registers new blockchain -func RegisterBlockchain(blockchain string) error { - b := Blockchain(blockchain) - if _, ok := blockchains[b]; ok { - return fmt.Errorf("blockchain %s already registered", blockchain) - } - blockchains[b] = b - return nil -} - // NetworkID is method specific network identifier type NetworkID string @@ -142,16 +132,6 @@ func GetNetwork(name string) (NetworkID, error) { return network, nil } -// RegisterNetwork registers new network -func RegisterNetwork(name string) error { - n := NetworkID(name) - if _, ok := networks[n]; ok { - return fmt.Errorf("network %s already registered", n) - } - networks[n] = n - return nil -} - // DIDMethodByte did method flag representation var DIDMethodByte = map[DIDMethod]byte{ DIDMethodIden3: 0b00000001, @@ -160,18 +140,18 @@ var DIDMethodByte = map[DIDMethod]byte{ } // RegisterDIDMethodWithByte registers new DID method with byte flag -func RegisterDIDMethodWithByte(method string, b byte) error { +func RegisterDIDMethodWithByte(m DIDMethod, b *byte) error { + didMethods[m] = m - m := DIDMethod(method) - if _, ok := didMethods[m]; ok { - return fmt.Errorf("DID method %s already registered", method) + if b == nil { + return nil } - didMethods[m] = m if _, ok := DIDMethodByte[m]; ok { - return fmt.Errorf("DID method byte %s already registered", method) + return fmt.Errorf("DID method %s already registered", m) } - DIDMethodByte[m] = b + + DIDMethodByte[m] = *b return nil } @@ -215,39 +195,48 @@ var DIDMethodNetwork = map[DIDMethod]map[DIDNetworkFlag]byte{ }, } +// DIDMethodNetworkOpts is a structure to represent DID method network options +type DIDMethodNetworkOpts struct { + Method DIDMethod + MethodByte *byte + Blockchain Blockchain + Network NetworkID + NetworkFlag byte + ChainID *int +} + // RegisterDIDMethodNetwork registers new DID method network -func RegisterDIDMethodNetwork(method DIDMethod, blockchain Blockchain, network NetworkID, b byte) error { +func RegisterDIDMethodNetwork(opts DIDMethodNetworkOpts) error { - if _, ok := didMethods[method]; !ok { - return fmt.Errorf("DID method %s not registered", method) - } + b := opts.Blockchain + n := opts.Network + m := opts.Method + blockchains[b] = b + networks[n] = n - if _, ok := blockchains[blockchain]; !ok { - return fmt.Errorf("blockchain %s not registered", blockchain) + err := RegisterDIDMethodWithByte(m, opts.MethodByte) + if err != nil { + return err } - if _, ok := networks[network]; !ok { - return fmt.Errorf("network %s not registered", network) - } + flg := DIDNetworkFlag{Blockchain: b, NetworkID: n} - flg := DIDNetworkFlag{Blockchain: blockchain, NetworkID: network} - if _, ok := DIDMethodNetwork[method][flg]; ok { - return fmt.Errorf("DID method network %s:%s:%s already registered", method, blockchain, network) + if _, ok := DIDMethodNetwork[m]; !ok { + DIDMethodNetwork[m] = map[DIDNetworkFlag]byte{} } - // check chainID - _, err := GetChainID(blockchain, network) + err = RegisterChainID(b, n, opts.ChainID) + if err != nil { return err } - if _, ok := DIDMethodNetwork[method]; !ok { - DIDMethodNetwork[method] = map[DIDNetworkFlag]byte{} - DIDMethodNetwork[method][flg] = b - return nil + 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[method][flg] = b + DIDMethodNetwork[m][flg] = opts.NetworkFlag return nil } diff --git a/did_test.go b/did_test.go index ad6a8fb..f82bc38 100644 --- a/did_test.go +++ b/did_test.go @@ -380,79 +380,127 @@ func ethAddrFromHex(ea string) [20]byte { return ethAddr } +func intPtr(i int) *int { + return &i +} +func bPtr(i byte) *byte { + return &i +} +func strPtr(s string) *string { + return &s +} func TestDID_Custom_Parse_DID(t *testing.T) { - var err error - err = RegisterBlockchain("test_chain") - require.NoError(t, err) - err = RegisterNetwork("test_net") - require.NoError(t, err) - err = RegisterDIDMethodWithByte("test_method", 0b00000011) - require.NoError(t, err) - err = RegisterChainID("test_chain", "test_net", 101) - require.NoError(t, err) - err = RegisterDIDMethodNetwork("test_method", "test_chain", "test_net", 0b0001_0001) - require.NoError(t, err) - err = RegisterDIDMethodWithByte("method", 0b0000_0100) - require.NoError(t, err) - err = RegisterBlockchain("chain") - require.NoError(t, err) - err = RegisterNetwork("network") - require.NoError(t, err) + 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, + }, + }, + } - var m DIDMethod - var b Blockchain - var n NetworkID - m, err = GetDIDMethod("method") - require.NoError(t, err) - b, err = GetBlockchain("chain") - require.NoError(t, err) - n, err = GetNetwork("network") - require.NoError(t, err) - err = RegisterChainID(b, n, 102) - require.NoError(t, err) - err = RegisterDIDMethodNetwork(m, b, n, 0b0001_0001) - require.NoError(t, err) + 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) + }) + } - err = RegisterChainID(b, Test, 103) - require.NoError(t, err) + d := helperBuildDIDFromType(t, "method", "chain", "network") + require.Equal(t, "4bb86obLkMrifHixMY62WM4iQQVr7u29cxWjMAinrT", d.IDStrings[2]) - err = RegisterDIDMethodNetwork(DIDMethodIden3, b, Test, 0b01000000|0b00000011) - require.NoError(t, err) - err = RegisterChainID(ReadOnly, n, 104) - require.NoError(t, err) - err = RegisterDIDMethodNetwork(DIDMethodIden3, ReadOnly, n, 0b01000000|0b00000011) + did3, err := w3c.ParseDID("did:method:chain:network:4bb86obLkMrifHixMY62WM4iQQVr7u29cxWjMAinrT") require.NoError(t, err) - err = RegisterDIDMethodNetwork(DIDMethodIden3, ReadOnly, n, 0b01010000|0b00000100) - require.EqualError(t, err, "DID method network iden3:readonly:network already registered") - - err = RegisterDIDMethodWithByte("method2", 0b0000_0101) - require.NoError(t, err) - err = RegisterBlockchain("chain2") - require.NoError(t, err) - err = RegisterNetwork("network2") + id, err := idFromDID(*did3) require.NoError(t, err) - err = RegisterChainID("chain2", "network2", 105) + require.Equal(t, "4bb86obLkMrifHixMY62WM4iQQVr7u29cxWjMAinrT", id.String()) + method, err := MethodFromID(id) require.NoError(t, err) + require.Equal(t, DIDMethod("method"), method) - err = RegisterDIDMethodNetwork("method2", "chain2", "network2", 0b0001_0001) + blockchain, err := BlockchainFromID(id) require.NoError(t, err) + require.Equal(t, Blockchain("chain"), blockchain) - d := helperBuildDIDFromType(t, "method2", "chain2", "network2") - require.Equal(t, d.IDStrings[2], "5UtG9EXvF25j3X5uycwr4uy7Hjhni8bMposv3Lgv8o") - did, err := w3c.ParseDID("did:method:chain:network:4bb86obLkMrifHixMY62WM4iQQVr7u29cxWjMAinrT") - require.NoError(t, err) - id, err := idFromDID(*did) - require.NoError(t, err) - require.Equal(t, "4bb86obLkMrifHixMY62WM4iQQVr7u29cxWjMAinrT", id.String()) - met, err := MethodFromID(id) - require.NoError(t, err) - require.Equal(t, met, m) - bl, err := BlockchainFromID(id) - require.NoError(t, err) - require.Equal(t, bl, b) - net, err := NetworkIDFromID(id) + networkID, err := NetworkIDFromID(id) require.NoError(t, err) - require.Equal(t, net, n) + require.Equal(t, NetworkID("network"), networkID) + } From 43513060218fb43458504406c2aebaab82a169ec Mon Sep 17 00:00:00 2001 From: Dimasik Kolezhniuk Date: Fri, 1 Dec 2023 10:38:15 +0100 Subject: [PATCH 06/10] Fix comments --- chain.go | 7 ++---- did.go | 62 ++++++++++++++++++++++++++++++++++------------------- did_test.go | 40 +++++++++++++++------------------- 3 files changed, 59 insertions(+), 50 deletions(-) diff --git a/chain.go b/chain.go index 0791ff7..8b48ef3 100644 --- a/chain.go +++ b/chain.go @@ -47,16 +47,13 @@ func ChainIDfromDID(did w3c.DID) (ChainID, error) { } // RegisterChainID registers chainID for blockchain and network -func RegisterChainID(blockchain Blockchain, network NetworkID, chainID *int) error { - if chainID == nil { - return nil - } +func RegisterChainID(blockchain Blockchain, network NetworkID, chainID int) error { 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) + chainIDs[k] = ChainID(chainID) return nil } diff --git a/did.go b/did.go index 6cbd4b2..afcd83c 100644 --- a/did.go +++ b/did.go @@ -140,18 +140,14 @@ var DIDMethodByte = map[DIDMethod]byte{ } // RegisterDIDMethodWithByte registers new DID method with byte flag -func RegisterDIDMethodWithByte(m DIDMethod, b *byte) error { +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 + DIDMethodByte[m] = b return nil } @@ -195,28 +191,49 @@ var DIDMethodNetwork = map[DIDMethod]map[DIDNetworkFlag]byte{ }, } -// DIDMethodNetworkOpts is a structure to represent DID method network options -type DIDMethodNetworkOpts struct { +// DIDMethodNetworkParams is a structure to represent DID method network options +type DIDMethodNetworkParams struct { Method DIDMethod - MethodByte *byte Blockchain Blockchain Network NetworkID NetworkFlag byte - ChainID *int + chainID *int + methodByte *byte +} + +// RegistrationOptions is a type for DID method network options +type RegistrationOptions func(params *DIDMethodNetworkParams) + +func WithChainID(chainID int) RegistrationOptions { + return func(params *DIDMethodNetworkParams) { + params.chainID = &chainID + } +} + +func WithDIDMethodByte(methodByte byte) RegistrationOptions { + return func(params *DIDMethodNetworkParams) { + params.methodByte = &methodByte + } } // RegisterDIDMethodNetwork registers new DID method network -func RegisterDIDMethodNetwork(opts DIDMethodNetworkOpts) error { +func RegisterDIDMethodNetwork(params DIDMethodNetworkParams, opts ...RegistrationOptions) error { + + for _, opt := range opts { + opt(¶ms) + } - b := opts.Blockchain - n := opts.Network - m := opts.Method + b := params.Blockchain + n := params.Network + m := params.Method blockchains[b] = b networks[n] = n - err := RegisterDIDMethodWithByte(m, opts.MethodByte) - if err != nil { - return err + if params.methodByte != nil { + err := RegisterDIDMethodWithByte(m, *params.methodByte) + if err != nil { + return err + } } flg := DIDNetworkFlag{Blockchain: b, NetworkID: n} @@ -225,10 +242,11 @@ func RegisterDIDMethodNetwork(opts DIDMethodNetworkOpts) error { DIDMethodNetwork[m] = map[DIDNetworkFlag]byte{} } - err = RegisterChainID(b, n, opts.ChainID) - - if err != nil { - return err + if params.chainID != nil { + err := RegisterChainID(b, n, *params.chainID) + if err != nil { + return err + } } if _, ok := DIDMethodNetwork[m][flg]; ok { @@ -236,7 +254,7 @@ func RegisterDIDMethodNetwork(opts DIDMethodNetworkOpts) error { m, b, n) } - DIDMethodNetwork[m][flg] = opts.NetworkFlag + DIDMethodNetwork[m][flg] = params.NetworkFlag return nil } diff --git a/did_test.go b/did_test.go index f82bc38..7be3802 100644 --- a/did_test.go +++ b/did_test.go @@ -380,66 +380,59 @@ func ethAddrFromHex(ea string) [20]byte { return ethAddr } -func intPtr(i int) *int { - return &i -} -func bPtr(i byte) *byte { - return &i -} func strPtr(s string) *string { return &s } func TestDID_Custom_Parse_DID(t *testing.T) { testCases := []struct { Description string - Data DIDMethodNetworkOpts + Data DIDMethodNetworkParams ErrorMsg *string + opts []RegistrationOptions }{ { Description: "register new did method network", - Data: DIDMethodNetworkOpts{ + Data: DIDMethodNetworkParams{ Method: "test_method", Blockchain: "test_chain", Network: "test_net", - ChainID: intPtr(101), - MethodByte: bPtr(0b00000011), NetworkFlag: 0b0001_0001, }, + opts: []RegistrationOptions{WithChainID(101), WithDIDMethodByte(0b00000011)}, }, { Description: "register one more new did method network", - Data: DIDMethodNetworkOpts{ + Data: DIDMethodNetworkParams{ Method: "method", Blockchain: "chain", Network: "network", - ChainID: intPtr(102), - MethodByte: bPtr(0b00000100), NetworkFlag: 0b0001_0001, }, + opts: []RegistrationOptions{WithChainID(102), WithDIDMethodByte(0b00000100)}, }, { Description: "register network to existing did method", - Data: DIDMethodNetworkOpts{ + Data: DIDMethodNetworkParams{ Method: DIDMethodIden3, Blockchain: "chain", Network: Test, - ChainID: intPtr(103), NetworkFlag: 0b01000000 | 0b00000011, }, + opts: []RegistrationOptions{WithChainID(103)}, }, { Description: "register one more network to existing did method", - Data: DIDMethodNetworkOpts{ + Data: DIDMethodNetworkParams{ Method: DIDMethodIden3, Blockchain: ReadOnly, Network: "network", - ChainID: intPtr(104), NetworkFlag: 0b01000000 | 0b00000011, }, + opts: []RegistrationOptions{WithChainID(104)}, }, { Description: "register already registered did method network", - Data: DIDMethodNetworkOpts{ + Data: DIDMethodNetworkParams{ Method: DIDMethodIden3, Blockchain: ReadOnly, Network: "network", @@ -449,30 +442,31 @@ func TestDID_Custom_Parse_DID(t *testing.T) { }, { Description: "register exited chain", - Data: DIDMethodNetworkOpts{ + Data: DIDMethodNetworkParams{ Method: DIDMethodIden3, Blockchain: ReadOnly, Network: "network", - ChainID: intPtr(104), NetworkFlag: 0b01000000 | 0b00000011, }, + opts: []RegistrationOptions{WithChainID(104)}, + ErrorMsg: strPtr("chainID readonly:network already registered"), }, { Description: "register known chain id to new did method", - Data: DIDMethodNetworkOpts{ + Data: DIDMethodNetworkParams{ Method: "method2", Blockchain: Polygon, Network: Mumbai, - MethodByte: bPtr(0b0000_0101), NetworkFlag: 0b0001_0001, }, + opts: []RegistrationOptions{WithDIDMethodByte(1)}, }, } for _, tc := range testCases { t.Run(tc.Description, func(t *testing.T) { - err := RegisterDIDMethodNetwork(tc.Data) + err := RegisterDIDMethodNetwork(tc.Data, tc.opts...) if tc.ErrorMsg != nil { require.EqualError(t, err, *tc.ErrorMsg) return From 274faf0f047ea4a0321ce3605ca013a5543c8d42 Mon Sep 17 00:00:00 2001 From: Dimasik Kolezhniuk Date: Tue, 5 Dec 2023 16:45:55 +0100 Subject: [PATCH 07/10] Fix comments --- did.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/did.go b/did.go index afcd83c..bc0f73a 100644 --- a/did.go +++ b/did.go @@ -121,6 +121,7 @@ var networks = map[NetworkID]NetworkID{ Sepolia: Sepolia, Test: Test, UnknownNetwork: UnknownNetwork, + NoNetwork: NoNetwork, } // GetNetwork returns network by name @@ -139,8 +140,8 @@ var DIDMethodByte = map[DIDMethod]byte{ DIDMethodOther: 0b11111111, } -// RegisterDIDMethodWithByte registers new DID method with byte flag -func RegisterDIDMethodWithByte(m DIDMethod, b byte) error { +// RegisterDIDMethod registers new DID method with byte flag +func RegisterDIDMethod(m DIDMethod, b byte) error { didMethods[m] = m if _, ok := DIDMethodByte[m]; ok { @@ -230,7 +231,7 @@ func RegisterDIDMethodNetwork(params DIDMethodNetworkParams, opts ...Registratio networks[n] = n if params.methodByte != nil { - err := RegisterDIDMethodWithByte(m, *params.methodByte) + err := RegisterDIDMethod(m, *params.methodByte) if err != nil { return err } From 87ce330cefe64fb9eda2b7c0622054b8d1a7578c Mon Sep 17 00:00:00 2001 From: Dimasik Kolezhniuk Date: Wed, 6 Dec 2023 16:55:57 +0100 Subject: [PATCH 08/10] Fix comments after discussion --- chain.go | 2 +- did.go | 79 +++++++++++++++++++++++++++------------- did_test.go | 103 +++++++++++++++++++++++++++++++++++++++------------- 3 files changed, 132 insertions(+), 52 deletions(-) diff --git a/chain.go b/chain.go index 8b48ef3..65b5238 100644 --- a/chain.go +++ b/chain.go @@ -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) { return fmt.Errorf("chainID %s:%s already registered", blockchain, network) } chainIDs[k] = ChainID(chainID) diff --git a/did.go b/did.go index bc0f73a..e9ee2a2 100644 --- a/did.go +++ b/did.go @@ -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 } @@ -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 @@ -128,11 +130,17 @@ var networks = map[NetworkID]NetworkID{ 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, @@ -142,12 +150,17 @@ var DIDMethodByte = map[DIDMethod]byte{ // RegisterDIDMethod registers new DID method with byte flag func RegisterDIDMethod(m DIDMethod, b byte) error { - didMethods[m] = m - if _, ok := DIDMethodByte[m]; ok { + if existingByte, ok := DIDMethodByte[m]; ok && existingByte != b { 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 @@ -198,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(¶ms) + opt(&o) } b := params.Blockchain n := params.Network m := params.Method - blockchains[b] = b - networks[n] = n - if params.methodByte != nil { - err := RegisterDIDMethod(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 } @@ -243,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) } diff --git a/did_test.go b/did_test.go index 7be3802..221a3c6 100644 --- a/did_test.go +++ b/did_test.go @@ -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 }{ { @@ -411,37 +407,37 @@ 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, @@ -449,8 +445,6 @@ func TestDID_Custom_Parse_DID(t *testing.T) { NetworkFlag: 0b01000000 | 0b00000011, }, opts: []RegistrationOptions{WithChainID(104)}, - - ErrorMsg: strPtr("chainID readonly:network already registered"), }, { Description: "register known chain id to new did method", @@ -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) }) } @@ -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) + }) + } + +} From 7d55e564a17da0a1cd2f5cd4c1f52cc67159d472 Mon Sep 17 00:00:00 2001 From: Dimasik Kolezhniuk Date: Wed, 6 Dec 2023 18:02:34 +0100 Subject: [PATCH 09/10] Fix comments --- chain.go | 4 ++-- did.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/chain.go b/chain.go index 65b5238..7b54981 100644 --- a/chain.go +++ b/chain.go @@ -48,9 +48,9 @@ func ChainIDfromDID(did w3c.DID) (ChainID, error) { // RegisterChainID registers chainID for blockchain and network func RegisterChainID(blockchain Blockchain, network NetworkID, chainID int) error { - k := fmt.Sprintf("%s:%s", blockchain, network) - if existingChainID, ok := chainIDs[k]; ok && existingChainID != ChainID(chainID) { + existingChainID, ok := chainIDs[k] + if ok && existingChainID != ChainID(chainID) { return fmt.Errorf("chainID %s:%s already registered", blockchain, network) } chainIDs[k] = ChainID(chainID) diff --git a/did.go b/did.go index e9ee2a2..a09875b 100644 --- a/did.go +++ b/did.go @@ -150,8 +150,8 @@ var DIDMethodByte = map[DIDMethod]byte{ // RegisterDIDMethod registers new DID method with byte flag func RegisterDIDMethod(m DIDMethod, b byte) error { - - if existingByte, ok := DIDMethodByte[m]; ok && existingByte != b { + existingByte, ok := DIDMethodByte[m] + if ok && existingByte != b { return fmt.Errorf("DID method %s already registered", m) } From a166dfb9154ef8b7d5356738b5a4f448c8d5a749 Mon Sep 17 00:00:00 2001 From: Dimasik Kolezhniuk Date: Wed, 6 Dec 2023 18:13:45 +0100 Subject: [PATCH 10/10] Fix error messages --- chain.go | 2 +- did.go | 10 +++++----- did_test.go | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/chain.go b/chain.go index 7b54981..4a4e61b 100644 --- a/chain.go +++ b/chain.go @@ -51,7 +51,7 @@ func RegisterChainID(blockchain Blockchain, network NetworkID, chainID int) erro k := fmt.Sprintf("%s:%s", blockchain, network) existingChainID, ok := chainIDs[k] if ok && existingChainID != ChainID(chainID) { - return fmt.Errorf("chainID %s:%s already registered", blockchain, network) + return fmt.Errorf("chainID '%s:%s' already registered with value %d", blockchain, network, existingChainID) } chainIDs[k] = ChainID(chainID) diff --git a/did.go b/did.go index a09875b..adf3008 100644 --- a/did.go +++ b/did.go @@ -152,7 +152,7 @@ var DIDMethodByte = map[DIDMethod]byte{ func RegisterDIDMethod(m DIDMethod, b byte) error { existingByte, ok := DIDMethodByte[m] if ok && existingByte != b { - return fmt.Errorf("DID method %s already registered", m) + return fmt.Errorf("DID method '%s' already registered with byte %b", m, existingByte) } max := DIDMethodByte[DIDMethodOther] @@ -276,10 +276,10 @@ func RegisterDIDMethodNetwork(params DIDMethodNetworkParams, opts ...Registratio return err } } - - 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) + 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 diff --git a/did_test.go b/did_test.go index 221a3c6..51e26b5 100644 --- a/did_test.go +++ b/did_test.go @@ -506,7 +506,7 @@ func TestCustomDIDRegistration_Negative(t *testing.T) { NetworkFlag: 0b0001_0001, }, opts: []RegistrationOptions{WithChainID(1)}, - err: "chainID polygon:mumbai already registered", + err: "chainID 'polygon:mumbai' already registered with value 80001", }, { Description: "try to overwrite existing DID method byte", @@ -517,7 +517,7 @@ func TestCustomDIDRegistration_Negative(t *testing.T) { NetworkFlag: 0b00100000 | 0b00000001, }, opts: []RegistrationOptions{WithChainID(1), WithDIDMethodByte(0b00000010)}, - err: "DID method iden3 already registered", + err: "DID method 'iden3' already registered with byte 1", }, { Description: "try to write max did method byte", @@ -539,7 +539,7 @@ func TestCustomDIDRegistration_Negative(t *testing.T) { NetworkFlag: 0b00100000 | 0b00000011, }, opts: nil, - err: "DID method network 'iden3' with blockchain 'eth' and network 'main' already registered", + err: "DID method network 'iden3' with blockchain 'eth' and network 'main' already registered with another flag '100001'", }, }