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

Add NetworkByChainID function to return network and blockchain for registered ChainID #460

Merged
merged 2 commits into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 2 additions & 2 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: 1.19.2
go-version: 1.21.6
- uses: golangci/golangci-lint-action@v3
with:
version: v1.50.0
version: v1.55.2
6 changes: 3 additions & 3 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ jobs:
strategy:
matrix:
containers:
- 1.17.13-bullseye
- 1.18.10-bullseye
- 1.19.5-bullseye
- 1.20.0-bullseye
- 1.19.13-bullseye
- 1.20.13-bullseye
- 1.21.6-bookworm
runs-on: ubuntu-20.04
container: golang:${{matrix.containers}}
steps:
Expand Down
74 changes: 55 additions & 19 deletions chain.go
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
package core

import (
"errors"
"fmt"
"sync"

"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,
type chainIDKey struct {
blockchain Blockchain
networkID NetworkID
}

var ErrChainIDNotRegistered = errors.New("chainID is not registered")

var chainIDsLock sync.RWMutex
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@olomix Do we really need sync.RWMutex here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What other options do we have to guard concurrent access to global dict?
We can use sync.Map. But typed map with lock I like more.


// chainIDs Object containing chain IDs for various blockchains and networks.
// It can be modified using RegisterChainID public function. So it is guarded
// by chainIDsLock mutex.
var chainIDs = map[chainIDKey]ChainID{
{Ethereum, Main}: 1,
{Ethereum, Goerli}: 5,
{Ethereum, Sepolia}: 11155111,
{Polygon, Main}: 137,
{Polygon, Mumbai}: 80001,
{ZkEVM, Main}: 1101,
{ZkEVM, Test}: 1442,
}

// ChainIDfromDID returns chain name from w3c.DID
Expand All @@ -38,25 +51,27 @@ func ChainIDfromDID(did w3c.DID) (ChainID, error) {
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
return GetChainID(blockchain, networkID)
}

// RegisterChainID registers chainID for blockchain and network
func RegisterChainID(blockchain Blockchain, network NetworkID, chainID int) error {
k := fmt.Sprintf("%s:%s", blockchain, network)
chainIDsLock.Lock()
defer chainIDsLock.Unlock()

k := chainIDKey{
blockchain: blockchain,
networkID: network,
}
existingChainID, ok := chainIDs[k]
if ok && existingChainID == ChainID(chainID) {
return nil
}

for _, v := range chainIDs {
if v == ChainID(chainID) {
return fmt.Errorf(`can't register chain id %d for '%s' because it's already registered for another chain id`, chainID, k)
return fmt.Errorf(`can't register chain id %d for '%v:%v' because it's already registered for another chain id`,
chainID, k.blockchain, k.networkID)
}
}

Expand All @@ -67,10 +82,31 @@ func RegisterChainID(blockchain Blockchain, network NetworkID, chainID int) erro

// GetChainID returns chainID for blockchain and network
func GetChainID(blockchain Blockchain, network NetworkID) (ChainID, error) {
k := fmt.Sprintf("%s:%s", blockchain, network)
chainIDsLock.RLock()
defer chainIDsLock.RUnlock()

k := chainIDKey{
blockchain: blockchain,
networkID: network,
}
if _, ok := chainIDs[k]; !ok {
return 0, fmt.Errorf("chainID not registered for %s:%s", blockchain, network)
return 0, fmt.Errorf("%w for %s:%s", ErrChainIDNotRegistered, blockchain,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Retrun NoChain constant?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NoChain has a Blockchain type, not ChainID.

network)
}

return chainIDs[k], nil
}

// NetworkByChainID returns blockchain and networkID for registered chain ID.
// Or ErrChainIDNotRegistered error if chainID is not registered.
func NetworkByChainID(chainID ChainID) (Blockchain, NetworkID, error) {
chainIDsLock.RLock()
defer chainIDsLock.RUnlock()

for k, v := range chainIDs {
if v == chainID {
return k.blockchain, k.networkID, nil
}
}
return NoChain, NoNetwork, ErrChainIDNotRegistered
}
16 changes: 16 additions & 0 deletions chain_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package core

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestNetworkByChainID(t *testing.T) {
chainID, err := GetChainID(Ethereum, Main)
require.NoError(t, err)
blockchain, networkID, err := NetworkByChainID(chainID)
require.NoError(t, err)
require.Equal(t, Ethereum, blockchain)
require.Equal(t, Main, networkID)
}
4 changes: 2 additions & 2 deletions did_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -569,8 +569,8 @@ func TestCustomDIDRegistration_Negative(t *testing.T) {
Network: Main,
NetworkFlag: 0b0001_0001,
},
opts: []RegistrationOptions{WithChainID(101), WithDIDMethodByte(0b10000000)},
err: "can't register chain id 101 for 'eth:main' because it's already registered for another chain id",
opts: []RegistrationOptions{WithChainID(137), WithDIDMethodByte(0b10000000)},
err: "can't register chain id 137 for 'eth:main' because it's already registered for another chain id",
},
{
Description: "register new network and chain with existing networkFlag for existing existing did method",
Expand Down
Loading