@obolnetwork/obol-sdk 1.0.8 → 1.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/cjs/src/ajv.js +17 -0
- package/dist/cjs/src/base.js +39 -0
- package/dist/cjs/src/constants.js +86 -0
- package/dist/cjs/src/errors.js +11 -0
- package/dist/cjs/src/hash.js +172 -0
- package/dist/cjs/src/index.js +158 -0
- package/dist/cjs/src/schema.js +72 -0
- package/dist/cjs/src/services.js +32 -0
- package/dist/cjs/src/types.js +18 -0
- package/dist/cjs/src/utils.js +11 -0
- package/dist/cjs/src/verify.js +326 -0
- package/dist/cjs/test/fixtures.js +101 -0
- package/dist/cjs/test/methods.test.js +128 -0
- package/dist/esm/src/ajv.js +10 -0
- package/dist/esm/src/base.js +35 -0
- package/dist/esm/src/constants.js +79 -0
- package/dist/esm/src/errors.js +7 -0
- package/dist/esm/src/hash.js +165 -0
- package/dist/esm/src/index.js +140 -0
- package/dist/esm/src/schema.js +69 -0
- package/dist/esm/src/services.js +28 -0
- package/dist/esm/src/types.js +15 -0
- package/dist/esm/src/utils.js +6 -0
- package/dist/esm/src/verify.js +295 -0
- package/dist/esm/test/fixtures.js +98 -0
- package/dist/esm/test/methods.test.js +126 -0
- package/dist/types/src/ajv.d.ts +2 -0
- package/dist/{base.d.ts → types/src/base.d.ts} +13 -14
- package/dist/types/src/constants.d.ts +79 -0
- package/dist/{errors.d.ts → types/src/errors.d.ts} +4 -5
- package/dist/{hash.d.ts → types/src/hash.d.ts} +56 -64
- package/dist/{index.d.ts → types/src/index.d.ts} +64 -49
- package/dist/types/src/schema.d.ts +57 -0
- package/dist/types/src/services.d.ts +11 -0
- package/dist/{types.d.ts → types/src/types.d.ts} +153 -150
- package/dist/types/src/utils.d.ts +2 -0
- package/dist/types/src/verify.d.ts +4 -0
- package/dist/{fixtures.d.ts → types/test/fixtures.d.ts} +61 -62
- package/dist/types/test/methods.test.d.ts +1 -0
- package/package.json +55 -21
- package/src/ajv.ts +11 -0
- package/src/base.ts +44 -0
- package/src/constants.ts +118 -0
- package/src/errors.ts +11 -0
- package/src/hash.ts +250 -0
- package/src/index.ts +160 -0
- package/src/schema.ts +70 -0
- package/src/services.ts +20 -0
- package/src/types.ts +211 -0
- package/src/utils.ts +7 -0
- package/src/verify.ts +479 -0
- package/dist/ajv.d.ts +0 -4
- package/dist/ajv.d.ts.map +0 -1
- package/dist/base.d.ts.map +0 -1
- package/dist/cluster.test.d.ts +0 -2
- package/dist/cluster.test.d.ts.map +0 -1
- package/dist/constants.d.ts +0 -18
- package/dist/constants.d.ts.map +0 -1
- package/dist/errors.d.ts.map +0 -1
- package/dist/fixtures.d.ts.map +0 -1
- package/dist/hash.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.es.js +0 -15527
- package/dist/index.js +0 -15531
- package/dist/types.d.ts.map +0 -1
|
@@ -1,62 +1,61 @@
|
|
|
1
|
-
export declare const clusterLockV1X7: {
|
|
2
|
-
cluster_definition: {
|
|
3
|
-
name: string;
|
|
4
|
-
creator: {
|
|
5
|
-
address: string;
|
|
6
|
-
config_signature: string;
|
|
7
|
-
};
|
|
8
|
-
operators: {
|
|
9
|
-
address: string;
|
|
10
|
-
enr: string;
|
|
11
|
-
config_signature: string;
|
|
12
|
-
enr_signature: string;
|
|
13
|
-
}[];
|
|
14
|
-
uuid: string;
|
|
15
|
-
version: string;
|
|
16
|
-
timestamp: string;
|
|
17
|
-
num_validators: number;
|
|
18
|
-
threshold: number;
|
|
19
|
-
validators: {
|
|
20
|
-
fee_recipient_address: string;
|
|
21
|
-
withdrawal_address: string;
|
|
22
|
-
}[];
|
|
23
|
-
dkg_algorithm: string;
|
|
24
|
-
fork_version: string;
|
|
25
|
-
config_hash: string;
|
|
26
|
-
definition_hash: string;
|
|
27
|
-
};
|
|
28
|
-
distributed_validators: {
|
|
29
|
-
distributed_public_key: string;
|
|
30
|
-
public_shares: string[];
|
|
31
|
-
deposit_data: {
|
|
32
|
-
pubkey: string;
|
|
33
|
-
withdrawal_credentials: string;
|
|
34
|
-
amount: string;
|
|
35
|
-
signature: string;
|
|
36
|
-
deposit_data_root: string;
|
|
37
|
-
};
|
|
38
|
-
builder_registration: {
|
|
39
|
-
message: {
|
|
40
|
-
fee_recipient: string;
|
|
41
|
-
gas_limit: number;
|
|
42
|
-
timestamp: number;
|
|
43
|
-
pubkey: string;
|
|
44
|
-
};
|
|
45
|
-
signature: string;
|
|
46
|
-
};
|
|
47
|
-
}[];
|
|
48
|
-
signature_aggregate: string;
|
|
49
|
-
lock_hash: string;
|
|
50
|
-
node_signatures: string[];
|
|
51
|
-
};
|
|
52
|
-
export declare const clusterConfig: {
|
|
53
|
-
name: string;
|
|
54
|
-
operators: {
|
|
55
|
-
address: string;
|
|
56
|
-
}[];
|
|
57
|
-
validators: {
|
|
58
|
-
fee_recipient_address: string;
|
|
59
|
-
withdrawal_address: string;
|
|
60
|
-
}[];
|
|
61
|
-
};
|
|
62
|
-
//# sourceMappingURL=fixtures.d.ts.map
|
|
1
|
+
export declare const clusterLockV1X7: {
|
|
2
|
+
cluster_definition: {
|
|
3
|
+
name: string;
|
|
4
|
+
creator: {
|
|
5
|
+
address: string;
|
|
6
|
+
config_signature: string;
|
|
7
|
+
};
|
|
8
|
+
operators: {
|
|
9
|
+
address: string;
|
|
10
|
+
enr: string;
|
|
11
|
+
config_signature: string;
|
|
12
|
+
enr_signature: string;
|
|
13
|
+
}[];
|
|
14
|
+
uuid: string;
|
|
15
|
+
version: string;
|
|
16
|
+
timestamp: string;
|
|
17
|
+
num_validators: number;
|
|
18
|
+
threshold: number;
|
|
19
|
+
validators: {
|
|
20
|
+
fee_recipient_address: string;
|
|
21
|
+
withdrawal_address: string;
|
|
22
|
+
}[];
|
|
23
|
+
dkg_algorithm: string;
|
|
24
|
+
fork_version: string;
|
|
25
|
+
config_hash: string;
|
|
26
|
+
definition_hash: string;
|
|
27
|
+
};
|
|
28
|
+
distributed_validators: {
|
|
29
|
+
distributed_public_key: string;
|
|
30
|
+
public_shares: string[];
|
|
31
|
+
deposit_data: {
|
|
32
|
+
pubkey: string;
|
|
33
|
+
withdrawal_credentials: string;
|
|
34
|
+
amount: string;
|
|
35
|
+
signature: string;
|
|
36
|
+
deposit_data_root: string;
|
|
37
|
+
};
|
|
38
|
+
builder_registration: {
|
|
39
|
+
message: {
|
|
40
|
+
fee_recipient: string;
|
|
41
|
+
gas_limit: number;
|
|
42
|
+
timestamp: number;
|
|
43
|
+
pubkey: string;
|
|
44
|
+
};
|
|
45
|
+
signature: string;
|
|
46
|
+
};
|
|
47
|
+
}[];
|
|
48
|
+
signature_aggregate: string;
|
|
49
|
+
lock_hash: string;
|
|
50
|
+
node_signatures: string[];
|
|
51
|
+
};
|
|
52
|
+
export declare const clusterConfig: {
|
|
53
|
+
name: string;
|
|
54
|
+
operators: {
|
|
55
|
+
address: string;
|
|
56
|
+
}[];
|
|
57
|
+
validators: {
|
|
58
|
+
fee_recipient_address: string;
|
|
59
|
+
withdrawal_address: string;
|
|
60
|
+
}[];
|
|
61
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,59 +1,93 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@obolnetwork/obol-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.11",
|
|
4
4
|
"description": "A package for creating Distributed Validators using the Obol API.",
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
"bugs": {
|
|
6
|
+
"url": "https://github.com/obolnetwork/obol-packages/issues"
|
|
7
|
+
},
|
|
8
|
+
"homepage": "https://docs.obol.tech/",
|
|
8
9
|
"keywords": [
|
|
9
10
|
"Obol",
|
|
10
11
|
"Distributed Validators",
|
|
11
12
|
"Ethereum"
|
|
12
13
|
],
|
|
13
|
-
"files": [
|
|
14
|
-
"dist"
|
|
15
|
-
],
|
|
16
14
|
"scripts": {
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
15
|
+
"compile": "tsc -b ./tsconfig.cjs.json ./tsconfig.esm.json ./tsconfig.types.json",
|
|
16
|
+
"build:clean": "rm -rf ./dist",
|
|
17
|
+
"build": "npm-run-all build:clean compile",
|
|
18
|
+
"test": "jest ./test/methods.test.ts",
|
|
20
19
|
"generate-typedoc": "typedoc",
|
|
21
20
|
"ds:release:major": "npm version $(semver $npm_package_version -i major) && npm publish --tag latest",
|
|
22
21
|
"ds:release:minor": "npm version $(semver $npm_package_version -i minor) && npm publish --tag latest",
|
|
23
|
-
"ds:release:patch": "npm
|
|
22
|
+
"ds:release:patch": "npm version $(semver $npm_package_version -i patch) && npm publish --tag latest"
|
|
24
23
|
},
|
|
24
|
+
"main": "./dist/cjs/src/index.js",
|
|
25
|
+
"module": "./dist/esm/src/index.js",
|
|
26
|
+
"typings": "./dist/types/src/index.d.ts",
|
|
25
27
|
"author": "Obol Labs (https://obol.tech)",
|
|
26
28
|
"repository": {
|
|
27
29
|
"type": "git",
|
|
28
30
|
"url": "git+https://github.com/obolnetwork/obol-packages.git"
|
|
29
31
|
},
|
|
30
32
|
"license": "ISC",
|
|
31
|
-
"bugs": {
|
|
32
|
-
"url": "https://github.com/obolnetwork/obol-packages/issues"
|
|
33
|
-
},
|
|
34
|
-
"homepage": "https://docs.obol.tech/",
|
|
35
33
|
"publishConfig": {
|
|
36
34
|
"registry": "https://registry.npmjs.org/",
|
|
37
35
|
"access": "public"
|
|
38
36
|
},
|
|
39
37
|
"dependencies": {
|
|
40
|
-
"@chainsafe/
|
|
38
|
+
"@chainsafe/bls": "6.0.3",
|
|
39
|
+
"@chainsafe/blst": "^0.2.9",
|
|
40
|
+
"@chainsafe/discv5": "^0.5.1",
|
|
41
|
+
"@chainsafe/ssz": "^0.14.0",
|
|
42
|
+
"@metamask/eth-sig-util": "^7.0.1",
|
|
41
43
|
"ajv": "^8.12.0",
|
|
42
44
|
"cross-fetch": "^3.1.5",
|
|
45
|
+
"elliptic": "^6.5.4",
|
|
43
46
|
"ethers": "^6.4.0",
|
|
47
|
+
"nock": "^13.5.3",
|
|
44
48
|
"uuid": "^9.0.0"
|
|
45
49
|
},
|
|
46
50
|
"devDependencies": {
|
|
51
|
+
"@types/elliptic": "^6.4.18",
|
|
47
52
|
"@types/jest": "^28.1.8",
|
|
48
53
|
"@types/node": "^20.2.5",
|
|
49
54
|
"@types/uuid": "^9.0.1",
|
|
50
|
-
"
|
|
55
|
+
"eslint": "^8.6.0",
|
|
51
56
|
"jest": "^28.1.3",
|
|
52
|
-
"
|
|
57
|
+
"msw": "^2.2.1",
|
|
58
|
+
"npm-run-all": "^4.1.5",
|
|
53
59
|
"ts-jest": "^28.0.8",
|
|
54
|
-
"tsconfig": "*",
|
|
55
60
|
"tsup": "^6.7.0",
|
|
56
|
-
"typedoc": "^0.
|
|
57
|
-
"
|
|
61
|
+
"typedoc": "^0.25.7",
|
|
62
|
+
"typedoc-plugin-markdown": "^4.0.0-next.50",
|
|
63
|
+
"typescript": "^5.3.3"
|
|
64
|
+
},
|
|
65
|
+
"engines": {
|
|
66
|
+
"node": ">= 16"
|
|
67
|
+
},
|
|
68
|
+
"files": [
|
|
69
|
+
"package.json",
|
|
70
|
+
"README.md",
|
|
71
|
+
"dist",
|
|
72
|
+
"src"
|
|
73
|
+
],
|
|
74
|
+
"jest": {
|
|
75
|
+
"transform": {
|
|
76
|
+
"\\.[jt]sx?$": "ts-jest"
|
|
77
|
+
},
|
|
78
|
+
"globals": {
|
|
79
|
+
"ts-jest": {
|
|
80
|
+
"useESM": true
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
"moduleNameMapper": {
|
|
84
|
+
"^bn.js$": "<rootDir>/node_modules/bn.js",
|
|
85
|
+
"^asn1.js$": "<rootDir>/node_modules/asn1.js",
|
|
86
|
+
"^hash.js$": "<rootDir>/node_modules/hash.js",
|
|
87
|
+
"(.+)\\.js": "$1"
|
|
88
|
+
},
|
|
89
|
+
"extensionsToTreatAsEsm": [
|
|
90
|
+
".ts"
|
|
91
|
+
]
|
|
58
92
|
}
|
|
59
93
|
}
|
package/src/ajv.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import Ajv, { ErrorObject } from 'ajv';
|
|
2
|
+
|
|
3
|
+
export function validatePayload(data: any, schema: any): ErrorObject[] | undefined | null | boolean {
|
|
4
|
+
const ajv = new Ajv();
|
|
5
|
+
const validate = ajv.compile(schema);
|
|
6
|
+
const isValid = validate(data);
|
|
7
|
+
if (!isValid) {
|
|
8
|
+
throw new Error(`Schema compilation errors', ${validate.errors && validate.errors[0].message}`);
|
|
9
|
+
}
|
|
10
|
+
return isValid;
|
|
11
|
+
}
|
package/src/base.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// src/resources/base.ts
|
|
2
|
+
import { DEFAULT_BASE_URL, DEFAULT_CHAIN_ID, SDK_VERSION } from './constants.js';
|
|
3
|
+
import { FORK_MAPPING } from './types.js';
|
|
4
|
+
|
|
5
|
+
type Config = {
|
|
6
|
+
baseUrl?: string;
|
|
7
|
+
chainId?: FORK_MAPPING;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export abstract class Base {
|
|
11
|
+
baseUrl: string;
|
|
12
|
+
chainId: number;
|
|
13
|
+
fork_version: string;
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
constructor({ baseUrl = DEFAULT_BASE_URL, chainId = DEFAULT_CHAIN_ID }: Config) {
|
|
18
|
+
this.baseUrl = baseUrl;
|
|
19
|
+
this.chainId = chainId;
|
|
20
|
+
this.fork_version = FORK_MAPPING[this.chainId]
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
protected async request<T>(endpoint: string, options?: RequestInit): Promise<T> {
|
|
24
|
+
const url = `${this.baseUrl}${endpoint}`
|
|
25
|
+
const config = {
|
|
26
|
+
...options,
|
|
27
|
+
headers: {
|
|
28
|
+
'Content-Type': 'application/json',
|
|
29
|
+
'User-Agent': `Obol-SDK/${SDK_VERSION}`,
|
|
30
|
+
...options?.headers
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
const response = await fetch(url, config);
|
|
36
|
+
if (response.ok) {
|
|
37
|
+
return (await response.json())
|
|
38
|
+
}
|
|
39
|
+
throw new Error(response.statusText);
|
|
40
|
+
} catch (e) {
|
|
41
|
+
throw e
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { TypedMessage } from "@metamask/eth-sig-util";
|
|
2
|
+
|
|
3
|
+
export const CONFLICT_ERROR_MSG = "Conflict"
|
|
4
|
+
|
|
5
|
+
export const EIP712_DOMAIN_NAME = "Obol";
|
|
6
|
+
export const EIP712_DOMAIN_VERSION = "1";
|
|
7
|
+
export const CreatorConfigHashSigningTypes = {
|
|
8
|
+
CreatorConfigHash: [{ name: "creator_config_hash", type: "string" }],
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const EIP712Domain = [
|
|
12
|
+
{ name: 'name', type: 'string' },
|
|
13
|
+
{ name: 'version', type: 'string' },
|
|
14
|
+
{ name: 'chainId', type: 'uint256' },
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
export const Domain = (chainId: number) => {
|
|
18
|
+
return {
|
|
19
|
+
name: EIP712_DOMAIN_NAME,
|
|
20
|
+
version: EIP712_DOMAIN_VERSION,
|
|
21
|
+
chainId,
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const CreatorTypedMessage = {
|
|
26
|
+
EIP712Domain,
|
|
27
|
+
...CreatorConfigHashSigningTypes
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
//A conflict once updateDefinition is merged
|
|
31
|
+
export const EnrSigningTypes = {
|
|
32
|
+
ENR: [{ name: "enr", type: "string" }],
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const OperatorConfigHashSigningTypes = {
|
|
36
|
+
OperatorConfigHash: [{ name: "operator_config_hash", type: "string" }],
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const OperatorTypedMessage = {
|
|
40
|
+
EIP712Domain,
|
|
41
|
+
...OperatorConfigHashSigningTypes
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const ENRTypedMessage = {
|
|
45
|
+
EIP712Domain,
|
|
46
|
+
...EnrSigningTypes
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const signCreatorConfigHashPayload = (
|
|
50
|
+
payload: { creator_config_hash: string },
|
|
51
|
+
chainId: number,
|
|
52
|
+
): TypedMessage<typeof CreatorTypedMessage> => {
|
|
53
|
+
return {
|
|
54
|
+
types: CreatorTypedMessage,
|
|
55
|
+
primaryType: 'CreatorConfigHash',
|
|
56
|
+
domain: {
|
|
57
|
+
name: EIP712_DOMAIN_NAME,
|
|
58
|
+
version: EIP712_DOMAIN_VERSION,
|
|
59
|
+
chainId,
|
|
60
|
+
},
|
|
61
|
+
message: payload,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export const signOperatorConfigHashPayload = (
|
|
66
|
+
payload: { operator_config_hash: string },
|
|
67
|
+
chainId: number,
|
|
68
|
+
): TypedMessage<typeof OperatorTypedMessage> => {
|
|
69
|
+
return {
|
|
70
|
+
types: OperatorTypedMessage,
|
|
71
|
+
primaryType: 'OperatorConfigHash',
|
|
72
|
+
domain: {
|
|
73
|
+
name: EIP712_DOMAIN_NAME,
|
|
74
|
+
version: EIP712_DOMAIN_VERSION,
|
|
75
|
+
chainId,
|
|
76
|
+
},
|
|
77
|
+
message: payload,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export const signEnrPayload = (
|
|
82
|
+
payload: { enr: string },
|
|
83
|
+
chainId: number,
|
|
84
|
+
): TypedMessage<typeof ENRTypedMessage> => {
|
|
85
|
+
return {
|
|
86
|
+
types: ENRTypedMessage,
|
|
87
|
+
primaryType: 'ENR',
|
|
88
|
+
domain: {
|
|
89
|
+
name: EIP712_DOMAIN_NAME,
|
|
90
|
+
version: EIP712_DOMAIN_VERSION,
|
|
91
|
+
chainId,
|
|
92
|
+
},
|
|
93
|
+
message: payload,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
export const dkg_algorithm = "default";
|
|
99
|
+
|
|
100
|
+
export const config_version = "v1.7.0";
|
|
101
|
+
|
|
102
|
+
export const SDK_VERSION = "1.0.7";
|
|
103
|
+
|
|
104
|
+
export const DOMAIN_APPLICATION_BUILDER = '00000001';
|
|
105
|
+
export const DOMAIN_DEPOSIT = '03000000';
|
|
106
|
+
export const GENESIS_VALIDATOR_ROOT =
|
|
107
|
+
'0000000000000000000000000000000000000000000000000000000000000000';
|
|
108
|
+
|
|
109
|
+
// Flow used to create defintion
|
|
110
|
+
export enum DefinitionFlow {
|
|
111
|
+
Group = 'LP-Group',
|
|
112
|
+
Solo = 'LP-Solo',
|
|
113
|
+
Charon = 'Charon-Command',
|
|
114
|
+
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export const DEFAULT_BASE_URL = "https://api.obol.tech";
|
|
118
|
+
export const DEFAULT_CHAIN_ID = 1;
|
package/src/errors.ts
ADDED
package/src/hash.ts
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ContainerType,
|
|
3
|
+
ByteVectorType,
|
|
4
|
+
UintNumberType,
|
|
5
|
+
ListCompositeType,
|
|
6
|
+
ByteListType,
|
|
7
|
+
fromHexString,
|
|
8
|
+
} from '@chainsafe/ssz';
|
|
9
|
+
import { UintNumberByteLen } from '@chainsafe/ssz/lib/type/uint.js';
|
|
10
|
+
import { ValueOfFields } from '@chainsafe/ssz/lib/view/container.js';
|
|
11
|
+
import { ClusterDefintion, ClusterLock } from './types.js';
|
|
12
|
+
import { strToUint8Array } from './utils.js';
|
|
13
|
+
|
|
14
|
+
//cluster-definition
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param cluster The cluster configuration or the cluster definition
|
|
18
|
+
* @param configOnly a boolean to indicate config hash or definition hash
|
|
19
|
+
* @returns The config hash or the definition hash in of the corresponding cluster
|
|
20
|
+
*/
|
|
21
|
+
export const clusterConfigOrDefinitionHash = (
|
|
22
|
+
cluster: ClusterDefintion,
|
|
23
|
+
configOnly: boolean,
|
|
24
|
+
): string => {
|
|
25
|
+
|
|
26
|
+
const definitionType = clusterDefinitionContainerType(configOnly);
|
|
27
|
+
const val = hashClusterDefinition(cluster, configOnly);
|
|
28
|
+
return (
|
|
29
|
+
'0x' + Buffer.from(definitionType.hashTreeRoot(val).buffer).toString('hex')
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const hashClusterDefinition = (
|
|
34
|
+
cluster: ClusterDefintion,
|
|
35
|
+
configOnly: boolean,
|
|
36
|
+
): ValueOfFields<DefinitionFields> => {
|
|
37
|
+
const definitionType = clusterDefinitionContainerType(configOnly);
|
|
38
|
+
|
|
39
|
+
const val = definitionType.defaultValue();
|
|
40
|
+
|
|
41
|
+
//order should be same as charon https://github.com/ObolNetwork/charon/blob/d00b31e6465a260a43ce40f15c47fb5a5b009042/cluster/ssz.go#L285
|
|
42
|
+
val.uuid = strToUint8Array(cluster.uuid);
|
|
43
|
+
val.name = strToUint8Array(cluster.name);
|
|
44
|
+
val.version = strToUint8Array(cluster.version);
|
|
45
|
+
val.timestamp = strToUint8Array(cluster.timestamp);
|
|
46
|
+
val.num_validators = cluster.num_validators;
|
|
47
|
+
val.threshold = cluster.threshold;
|
|
48
|
+
val.dkg_algorithm = strToUint8Array(cluster.dkg_algorithm);
|
|
49
|
+
val.fork_version = fromHexString(cluster.fork_version);
|
|
50
|
+
val.operators = cluster.operators.map((operator) => {
|
|
51
|
+
return configOnly
|
|
52
|
+
? { address: fromHexString(operator.address) }
|
|
53
|
+
: {
|
|
54
|
+
address: fromHexString(operator.address),
|
|
55
|
+
enr: strToUint8Array(operator.enr as string),
|
|
56
|
+
config_signature: fromHexString(operator.config_signature as string),
|
|
57
|
+
enr_signature: fromHexString(operator.enr_signature as string),
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
val.creator = configOnly
|
|
61
|
+
? { address: fromHexString(cluster.creator.address) }
|
|
62
|
+
: {
|
|
63
|
+
address: fromHexString(cluster.creator.address),
|
|
64
|
+
config_signature: fromHexString(cluster.creator.config_signature as string),
|
|
65
|
+
};
|
|
66
|
+
val.validators = cluster.validators.map((validator: { fee_recipient_address: string; withdrawal_address: string; }) => {
|
|
67
|
+
return {
|
|
68
|
+
fee_recipient_address: fromHexString(validator.fee_recipient_address),
|
|
69
|
+
withdrawal_address: fromHexString(validator.withdrawal_address),
|
|
70
|
+
};
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
if (!configOnly) {
|
|
74
|
+
val.config_hash = fromHexString(cluster.config_hash);
|
|
75
|
+
}
|
|
76
|
+
return val;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const operatorAddressWrapperType = new ContainerType({
|
|
80
|
+
address: new ByteVectorType(20),
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const creatorAddressWrapperType = new ContainerType({
|
|
84
|
+
address: new ByteVectorType(20),
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
export const operatorContainerType = new ContainerType({
|
|
88
|
+
address: new ByteVectorType(20),
|
|
89
|
+
enr: new ByteListType(1024), // This needs to be dynamic, since ENRs do not have a fixed length.
|
|
90
|
+
config_signature: new ByteVectorType(65),
|
|
91
|
+
enr_signature: new ByteVectorType(65),
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
export const creatorContainerType = new ContainerType({
|
|
95
|
+
address: new ByteVectorType(20),
|
|
96
|
+
config_signature: new ByteVectorType(65),
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
export const validatorsContainerType = new ContainerType({
|
|
100
|
+
fee_recipient_address: new ByteVectorType(20),
|
|
101
|
+
withdrawal_address: new ByteVectorType(20),
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const newCreatorContainerType = (configOnly: boolean) => {
|
|
105
|
+
return configOnly ? creatorAddressWrapperType : creatorContainerType;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const newOperatorContainerType = (configOnly: boolean) => {
|
|
109
|
+
return configOnly ? operatorAddressWrapperType : operatorContainerType;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
type DefinitionFields = {
|
|
113
|
+
uuid: ByteListType;
|
|
114
|
+
name: ByteListType;
|
|
115
|
+
version: ByteListType;
|
|
116
|
+
timestamp: ByteListType;
|
|
117
|
+
num_validators: UintNumberType;
|
|
118
|
+
threshold: UintNumberType;
|
|
119
|
+
dkg_algorithm: ByteListType;
|
|
120
|
+
fork_version: ByteVectorType;
|
|
121
|
+
operators: ListCompositeType<
|
|
122
|
+
typeof operatorContainerType | typeof operatorAddressWrapperType
|
|
123
|
+
>;
|
|
124
|
+
creator: typeof creatorContainerType | typeof creatorAddressWrapperType;
|
|
125
|
+
validators: ListCompositeType<typeof validatorsContainerType>;
|
|
126
|
+
config_hash?: ByteVectorType;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
export type DefinitionContainerType =
|
|
130
|
+
ContainerType<DefinitionFields>;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* @param configOnly a boolean to indicate config hash or definition hash
|
|
134
|
+
* @returns SSZ Containerized type of cluster definition
|
|
135
|
+
*/
|
|
136
|
+
export const clusterDefinitionContainerType = (
|
|
137
|
+
configOnly: boolean,
|
|
138
|
+
): DefinitionContainerType => {
|
|
139
|
+
let returnedContainerType: DefinitionFields = {
|
|
140
|
+
uuid: new ByteListType(64),
|
|
141
|
+
name: new ByteListType(256),
|
|
142
|
+
version: new ByteListType(16),
|
|
143
|
+
timestamp: new ByteListType(32),
|
|
144
|
+
num_validators: new UintNumberType(8 as UintNumberByteLen),
|
|
145
|
+
threshold: new UintNumberType(8 as UintNumberByteLen),
|
|
146
|
+
dkg_algorithm: new ByteListType(32),
|
|
147
|
+
fork_version: new ByteVectorType(4),
|
|
148
|
+
operators: new ListCompositeType(newOperatorContainerType(configOnly), 256),
|
|
149
|
+
creator: newCreatorContainerType(configOnly),
|
|
150
|
+
validators: new ListCompositeType(validatorsContainerType, 65536),
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
if (!configOnly) {
|
|
154
|
+
returnedContainerType = {
|
|
155
|
+
...returnedContainerType,
|
|
156
|
+
config_hash: new ByteVectorType(32),
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return new ContainerType(returnedContainerType);
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
//cluster-lock
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* @param cluster The published cluster lock
|
|
167
|
+
* @returns The lock hash in of the corresponding cluster
|
|
168
|
+
*/
|
|
169
|
+
export const clusterLockHash = (cluster: ClusterLock): string => {
|
|
170
|
+
const lockType = clusterLockContainerType();
|
|
171
|
+
|
|
172
|
+
const val = lockType.defaultValue();
|
|
173
|
+
|
|
174
|
+
//Check if we can replace with definition_hash
|
|
175
|
+
val.cluster_definition = hashClusterDefinition(
|
|
176
|
+
cluster.cluster_definition,
|
|
177
|
+
false,
|
|
178
|
+
);
|
|
179
|
+
val.distributed_validators = cluster.distributed_validators.map(dVaidator => {
|
|
180
|
+
return {
|
|
181
|
+
distributed_public_key: fromHexString(dVaidator.distributed_public_key),
|
|
182
|
+
public_shares: dVaidator.public_shares.map(publicShare =>
|
|
183
|
+
fromHexString(publicShare),
|
|
184
|
+
),
|
|
185
|
+
deposit_data: {
|
|
186
|
+
pubkey: fromHexString(dVaidator.deposit_data.pubkey as string),
|
|
187
|
+
withdrawal_credentials: fromHexString(
|
|
188
|
+
dVaidator.deposit_data.withdrawal_credentials as string
|
|
189
|
+
),
|
|
190
|
+
amount: parseInt(dVaidator.deposit_data.amount as string),
|
|
191
|
+
signature: fromHexString(dVaidator.deposit_data.signature as string),
|
|
192
|
+
},
|
|
193
|
+
builder_registration: {
|
|
194
|
+
message: {
|
|
195
|
+
fee_recipient: fromHexString(
|
|
196
|
+
dVaidator.builder_registration.message.fee_recipient,
|
|
197
|
+
),
|
|
198
|
+
gas_limit: dVaidator.builder_registration.message.gas_limit,
|
|
199
|
+
timestamp: dVaidator.builder_registration.message.timestamp,
|
|
200
|
+
pubkey: fromHexString(dVaidator.builder_registration.message.pubkey),
|
|
201
|
+
},
|
|
202
|
+
signature: fromHexString(dVaidator.builder_registration.signature),
|
|
203
|
+
},
|
|
204
|
+
};
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
return '0x' + Buffer.from(lockType.hashTreeRoot(val).buffer).toString('hex');
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
const depositDataContainer = new ContainerType({
|
|
211
|
+
pubkey: new ByteVectorType(48),
|
|
212
|
+
withdrawal_credentials: new ByteVectorType(32),
|
|
213
|
+
amount: new UintNumberType(8 as UintNumberByteLen),
|
|
214
|
+
signature: new ByteVectorType(96),
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
const builderRegistrationMessageContainer = new ContainerType({
|
|
219
|
+
fee_recipient: new ByteVectorType(20),
|
|
220
|
+
gas_limit: new UintNumberType(8 as UintNumberByteLen),
|
|
221
|
+
timestamp: new UintNumberType(8 as UintNumberByteLen),
|
|
222
|
+
pubkey: new ByteVectorType(48),
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
const builderRegistrationContainer = new ContainerType({
|
|
226
|
+
message: builderRegistrationMessageContainer,
|
|
227
|
+
signature: new ByteVectorType(96),
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
const dvContainerType = new ContainerType({
|
|
231
|
+
distributed_public_key: new ByteVectorType(48),
|
|
232
|
+
public_shares: new ListCompositeType(new ByteVectorType(48), 256),
|
|
233
|
+
deposit_data: depositDataContainer,
|
|
234
|
+
builder_registration: builderRegistrationContainer,
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
type LockContainerType = ContainerType<{
|
|
238
|
+
cluster_definition: DefinitionContainerType;
|
|
239
|
+
distributed_validators: ListCompositeType<typeof dvContainerType>;
|
|
240
|
+
}>;
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* @returns SSZ Containerized type of cluster lock
|
|
244
|
+
*/
|
|
245
|
+
const clusterLockContainerType = (): LockContainerType => {
|
|
246
|
+
return new ContainerType({
|
|
247
|
+
cluster_definition: clusterDefinitionContainerType(false),
|
|
248
|
+
distributed_validators: new ListCompositeType(dvContainerType, 65536),
|
|
249
|
+
});
|
|
250
|
+
};
|