Skip to content

Commit

Permalink
Merge branch 'master' into tx-new-release-v301
Browse files Browse the repository at this point in the history
  • Loading branch information
holgerd77 authored Jan 19, 2021
2 parents 8ff7377 + 16abc7b commit 60bc6da
Show file tree
Hide file tree
Showing 15 changed files with 344 additions and 81 deletions.
46 changes: 41 additions & 5 deletions packages/common/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ c.bootstrapNodes() // Array with current nodes
If the initializing library only supports a certain range of `hardforks` you can use the `supportedHardforks` option to restrict hardfork access on the `Common` instance:

```typescript
let c = new Common({
const c = new Common({
chain: 'ropsten',
supportedHardforks: ['byzantium', 'constantinople', 'petersburg'],
})
Expand Down Expand Up @@ -104,12 +104,48 @@ files like `mainnet.json` in the `chains` directory, or to the `Chain` type in [

### Working with private/custom chains

There are two ways to set up a common instance with parameters for a private/custom chain:
There are two distinct APIs available for setting up custom(ized) chains.

1. You can pass a dictionary - conforming to the parameter format described above - with your custom values in
the constructor or the `setChain()` method for the `chain` parameter.
### Activate with a single custom Chain setup

2. You can base your custom chain's config in a standard one, using the `Common.forCustomChain` method.
If you want to initialize a `Common` instance with a single custom chain which is then directly activated
you can pass a dictionary - conforming to the parameter format described above - with your custom chain
values to the constructor using the `chain` parameter or the `setChain()` method, here is some example:

```typescript
import myCustomChain from './[PATH]/myCustomChain.json'
const common = new Common({ chain: myCustomChain })
```

If you just want to change some certain parameters on a chain configuration it can also be conveniened to use
the `Common.forCustomChain()` method. With this method you can base your custom chain configuration with
a standard one (so using all the values from `baseChain` as the default values) and then just provide the
parameters you want to override:

```typescript
const customChainParams = { name: 'custom', chainId: 123, networkId: 678 }
const customChainCommon = Common.forCustomChain('mainnet', customChainParams, 'byzantium')
```

### Initialize using customChains Array

A second way for custom chain initialization is to use the `customChains` constructor option. This
option comes with more flexibility and allows for an arbitrary number of custom chains to be initialized on
a common instance in addition to the already supported ones. It also allows for an activation-independent
initialization, so you can add your chains by adding to the `customChains` array and either directly
use the `chain` option to activate one of the custom chains passed or activate a build in chain
(e.g. `mainnet`) and switch to other chains - including the custom ones - by using `Common.setChain()`.

```typescript
import myCustomChain1 from './[PATH]/myCustomChain1.json'
import myCustomChain2 from './[PATH]/myCustomChain2.json'
// Add two custom chains, initial mainnet activation
const common1 = new Common({ chain: 'mainnet', customChains: [ myCustomChain1, myCustomChain2 ] })
// Somewhat later down the road...
common1.setChain('customChain1')
// Add two custom chains, activate customChain1
const common1 = new Common({ chain: 'customChain1', customChains: [ myCustomChain1, myCustomChain2 ] })
```

## Hardforks

Expand Down
1 change: 1 addition & 0 deletions packages/common/src/chains/goerli.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "goerli",
"chainId": 5,
"networkId": 5,
"defaultHardfork": "istanbul",
"consensus": {
"type": "poa",
"algorithm": "clique"
Expand Down
44 changes: 35 additions & 9 deletions packages/common/src/chains/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,42 @@
import { chainsType } from './../types'
import { Chain, chainsType } from './../types'
import mainnet from './mainnet.json'
import ropsten from './ropsten.json'
import rinkeby from './rinkeby.json'
import kovan from './kovan.json'
import goerli from './goerli.json'

export const chains: chainsType = {
names: {
/**
* @hidden
*/
export function _getInitializedChains(customChains?: Chain[]) {
const names: any = {
'1': 'mainnet',
'3': 'ropsten',
'4': 'rinkeby',
'42': 'kovan',
'5': 'goerli',
},
mainnet: require('./mainnet.json'),
ropsten: require('./ropsten.json'),
rinkeby: require('./rinkeby.json'),
kovan: require('./kovan.json'),
goerli: require('./goerli.json'),
}
const chains: any = {
mainnet,
ropsten,
rinkeby,
kovan,
goerli,
}
if (customChains) {
for (const chain of customChains) {
const name = chain.name
names[chain.chainId.toString()] = name
chains[name] = chain
}
}

chains['names'] = names
return chains
}

/**
* @deprecated this constant will be internalized (removed)
* on next major version update
*/
export const chains: chainsType = _getInitializedChains()
1 change: 1 addition & 0 deletions packages/common/src/chains/kovan.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "kovan",
"chainId": 42,
"networkId": 42,
"defaultHardfork": "istanbul",
"consensus": {
"type": "poa",
"algorithm": "aura"
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/chains/mainnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "mainnet",
"chainId": 1,
"networkId": 1,
"defaultHardfork": "istanbul",
"consensus": {
"type": "pow",
"algorithm": "ethash"
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/chains/rinkeby.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "rinkeby",
"chainId": 4,
"networkId": 4,
"defaultHardfork": "istanbul",
"consensus": {
"type": "poa",
"algorithm": "clique"
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/chains/ropsten.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "ropsten",
"chainId": 3,
"networkId": 3,
"defaultHardfork": "istanbul",
"consensus": {
"type": "pow",
"algorithm": "ethash"
Expand Down
43 changes: 33 additions & 10 deletions packages/common/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { buf as crc32Buffer } from 'crc-32'
import { chains as chainParams } from './chains'
import { _getInitializedChains } from './chains'
import { hardforks as HARDFORK_CHANGES } from './hardforks'
import { EIPs } from './eips'
import { Chain } from './types'
Expand All @@ -9,7 +9,8 @@ import { Chain } from './types'
*/
export interface CommonOpts {
/**
* String ('mainnet') or Number (1) chain
* Chain name ('mainnet') or id (1), either from a chain directly supported
* or a custom chain passed in via `customChains`
*/
chain: string | number | object
/**
Expand All @@ -31,6 +32,18 @@ export interface CommonOpts {
* - [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537) - BLS12-381 precompiles
*/
eips?: number[]
/**
* Initialize (in addition to the supported chains) with the selected
* custom chains
*
* Usage (directly with the respective chain intialization via the `chain` option):
*
* ```javascript
* import myCustomChain1 from '[PATH_TO_MY_CHAINS]/myCustomChain1.json'
* const common = new Common({ chain: 'myCustomChain1', customChains: [ myCustomChain1 ]})
* ```
*/
customChains?: Chain[]
}

interface hardforkOptions {
Expand All @@ -44,12 +57,13 @@ interface hardforkOptions {
* Common class to access chain and hardfork parameters
*/
export default class Common {
readonly DEFAULT_HARDFORK: string = 'istanbul'
readonly DEFAULT_HARDFORK: string

private _chainParams: Chain
private _hardfork: string
private _supportedHardforks: Array<string> = []
private _eips: number[] = []
private _customChains: Chain[]

/**
* Creates a Common object for a custom chain, based on a standard one. It uses all the [[Chain]]
Expand Down Expand Up @@ -79,17 +93,19 @@ export default class Common {
})
}

private static _getChainParams(chain: string | number): Chain {
private static _getChainParams(chain: string | number, customChains?: Chain[]): Chain {
const initializedChains: any = _getInitializedChains(customChains)
if (typeof chain === 'number') {
if (chainParams['names'][chain]) {
return chainParams[chainParams['names'][chain]]
if (initializedChains['names'][chain]) {
const name: string = initializedChains['names'][chain]
return initializedChains[name]
}

throw new Error(`Chain with ID ${chain} not supported`)
}

if (chainParams[chain]) {
return chainParams[chain]
if (initializedChains[chain]) {
return initializedChains[chain]
}

throw new Error(`Chain with name ${chain} not supported`)
Expand All @@ -99,7 +115,9 @@ export default class Common {
* @constructor
*/
constructor(opts: CommonOpts) {
this._customChains = opts.customChains ?? []
this._chainParams = this.setChain(opts.chain)
this.DEFAULT_HARDFORK = this._chainParams.defaultHardfork ?? 'istanbul'
this._hardfork = this.DEFAULT_HARDFORK
if (opts.supportedHardforks) {
this._supportedHardforks = opts.supportedHardforks
Expand All @@ -120,8 +138,13 @@ export default class Common {
*/
setChain(chain: string | number | object): any {
if (typeof chain === 'number' || typeof chain === 'string') {
this._chainParams = Common._getChainParams(chain)
this._chainParams = Common._getChainParams(chain, this._customChains)
} else if (typeof chain === 'object') {
if (this._customChains.length > 0) {
throw new Error(
'Chain must be a string or number when initialized with customChains passed in'
)
}
const required = ['networkId', 'genesis', 'hardforks', 'bootstrapNodes']
for (const param of required) {
if ((<any>chain)[param] === undefined) {
Expand Down Expand Up @@ -613,7 +636,7 @@ export default class Common {
* @returns chain name (lower case)
*/
chainName(): string {
return chainParams['names'][this.chainId()] || (<any>this._chainParams)['name']
return (<any>this._chainParams)['name']
}

/**
Expand Down
8 changes: 8 additions & 0 deletions packages/common/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,18 @@ export interface Chain {
name: string
chainId: number
networkId: number
// TODO: make mandatory in next breaking release
defaultHardfork?: string
comment: string
url: string
genesis: GenesisBlock
hardforks: Hardfork[]
bootstrapNodes: BootstrapNode[]
// TODO: make mandatory in next breaking release
consensus?: {
type: string
algorithm: string
}
}

export interface eipsType {
Expand All @@ -40,6 +47,7 @@ export interface GenesisBlock {
export interface Hardfork {
name: string
block: number | null
forkHash?: string | null
}

export interface BootstrapNode {
Expand Down
35 changes: 0 additions & 35 deletions packages/common/tests/chains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,39 +119,4 @@ tape('[Common]: Initialization / Chain params', function (t: tape.Test) {

st.end()
})

t.test(
'Should provide correct access to private network chain parameters',
function (st: tape.Test) {
const chainParams = require('./testnet.json')
const c = new Common({ chain: chainParams, hardfork: 'byzantium' })
st.equal(c.chainName(), 'testnet', 'should initialize with chain name')
st.equal(c.chainId(), 12345, 'should return correct chain Id')
st.equal(c.networkId(), 12345, 'should return correct network Id')
st.equal(
c.genesis().hash,
'0xaa00000000000000000000000000000000000000000000000000000000000000',
'should return correct genesis hash'
)
st.equal(c.hardforks()[3]['block'], 3, 'should return correct hardfork data')
st.equal(c.bootstrapNodes()[1].ip, '10.0.0.2', 'should return a bootstrap node array')

st.end()
}
)

t.test('Should handle custom chain parameters with missing field', function (st: tape.Test) {
const chainParams = require('./testnet.json')
delete chainParams['hardforks']
st.throws(
function () {
new Common({ chain: chainParams })
},
/Missing required/,
'should throw an exception on missing parameter'
) // eslint-disable-line no-new

st.comment('-----------------------------------------------------------------')
st.end()
})
})
Loading

0 comments on commit 60bc6da

Please sign in to comment.