@pvium/p2id-core 0.1.0
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 +239 -0
- package/contracts/P2IDVault.sol +736 -0
- package/contracts/PviumIdentity.sol +268 -0
- package/contracts/PviumP2IDPolicy.sol +78 -0
- package/contracts/PviumP2IdVaultFactory.sol +327 -0
- package/contracts/PviumVerifier.sol +165 -0
- package/contracts/PviumZKVerifier.sol +2465 -0
- package/contracts/interfaces/IP2IDPolicy.sol +39 -0
- package/contracts/interfaces/IP2IDVault.sol +112 -0
- package/contracts/interfaces/IP2IDVerifier.sol +44 -0
- package/contracts/interfaces/IP2IdVaultFactory.sol +49 -0
- package/contracts/interfaces/IPviumIdentity.sol +28 -0
- package/contracts/lib/P2IDHash.sol +63 -0
- package/dist/cjs/identity.js +68 -0
- package/dist/cjs/identityNames.js +49 -0
- package/dist/cjs/index.js +24 -0
- package/dist/cjs/p2id.js +91 -0
- package/dist/cjs/p2idConstants.js +16 -0
- package/dist/cjs/package.json +3 -0
- package/dist/esm/identity.d.ts +38 -0
- package/dist/esm/identity.js +61 -0
- package/dist/esm/identityNames.d.ts +43 -0
- package/dist/esm/identityNames.js +44 -0
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/p2id.d.ts +54 -0
- package/dist/esm/p2id.js +82 -0
- package/dist/esm/p2idConstants.d.ts +30 -0
- package/dist/esm/p2idConstants.js +13 -0
- package/dist/esm/package.json +3 -0
- package/dist/identity.d.ts +38 -0
- package/dist/identity.js +61 -0
- package/dist/identityNames.d.ts +43 -0
- package/dist/identityNames.js +44 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/p2id.d.ts +54 -0
- package/dist/p2id.js +82 -0
- package/dist/p2idConstants.d.ts +38 -0
- package/dist/p2idConstants.js +21 -0
- package/package.json +44 -0
package/dist/p2id.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { keccak_256 } from '@noble/hashes/sha3';
|
|
2
|
+
import { identityHash as hashIdentity, toHex } from './identity.js';
|
|
3
|
+
import { resolveIdentityType } from './identityNames.js';
|
|
4
|
+
import { P2ID_SCHEME, P2ID_SCHEMES } from './p2idConstants.js';
|
|
5
|
+
export { P2ID_SCHEME, P2ID_SCHEMES };
|
|
6
|
+
/**
|
|
7
|
+
* P2ID address derivation.
|
|
8
|
+
*
|
|
9
|
+
* identityHash = sha256(identityDomain ‖ byte(typeId) ‖ normalize(value))
|
|
10
|
+
* p2id = keccak256(0xff ‖ factory ‖ identityHash ‖ vaultInitCodeHash)[12..]
|
|
11
|
+
*
|
|
12
|
+
* `normalize` ASCII-lowercases every type except phone and wallet, and lowercases `0x…` wallet
|
|
13
|
+
* addresses. A *scheme* (`p2id.vault.vN`) fixes the three constants: the identity domain, the
|
|
14
|
+
* vault creation-code hash and the factory. The factory is deployed through the deterministic
|
|
15
|
+
* deployment proxy, so it is at the same address on every EVM chain: a P2ID address is
|
|
16
|
+
* chain-agnostic, like any wallet address. (The vault contract still has to be deployed on each
|
|
17
|
+
* chain where it is claimed; anyone can do that, and funds sent before then are claimable once
|
|
18
|
+
* it is.)
|
|
19
|
+
*
|
|
20
|
+
* Each Pvium environment is its own stack: `production` (mainnets, the production Privy app) and
|
|
21
|
+
* `sandbox` (testnets, the sandbox Privy app) have different factories, so the same identity has
|
|
22
|
+
* a different address in each. Production is the default.
|
|
23
|
+
*
|
|
24
|
+
* Schemes are history. A change to the vault bytecode moves every address, so it ships as the
|
|
25
|
+
* next scheme and becomes `P2ID_SCHEME`; earlier schemes stay in `P2ID_SCHEMES` so addresses
|
|
26
|
+
* people were already given can be derived, and claimed, forever.
|
|
27
|
+
*/
|
|
28
|
+
/** Constants of a scheme; defaults to the current one. */
|
|
29
|
+
export function p2idScheme(name = P2ID_SCHEME) {
|
|
30
|
+
const s = P2ID_SCHEMES[name];
|
|
31
|
+
if (!s)
|
|
32
|
+
throw new Error(`unknown P2ID scheme "${name}" (known: ${Object.keys(P2ID_SCHEMES).join(', ')})`);
|
|
33
|
+
return s;
|
|
34
|
+
}
|
|
35
|
+
/** The identity commitment: the CREATE2 salt of the identity's vault and the value proofs bind. */
|
|
36
|
+
export function identityHash(type, value, scheme = P2ID_SCHEME) {
|
|
37
|
+
return hashIdentity(resolveIdentityType(type), value, p2idScheme(scheme).identityDomain);
|
|
38
|
+
}
|
|
39
|
+
/** The P2ID address for an identity: where to pay it, on any EVM chain, deployed or not. Checksummed. */
|
|
40
|
+
export function p2idAddress(input) {
|
|
41
|
+
const salt = identityHash(input.identityType, input.identityValue, input.scheme);
|
|
42
|
+
return p2idAddressForHash(salt, { scheme: input.scheme, environment: input.environment, factory: input.factory });
|
|
43
|
+
}
|
|
44
|
+
/** Same, from an identity hash you already have (e.g. from an attestation's claim). */
|
|
45
|
+
export function p2idAddressForHash(identityHash, opts = {}) {
|
|
46
|
+
const scheme = p2idScheme(opts.scheme);
|
|
47
|
+
const environment = opts.environment ?? 'production';
|
|
48
|
+
if (environment !== 'production' && environment !== 'sandbox')
|
|
49
|
+
throw new Error(`unknown environment "${environment}"`);
|
|
50
|
+
const factory = opts.factory ?? scheme.factories[environment];
|
|
51
|
+
if (!factory) {
|
|
52
|
+
throw new Error(`scheme ${opts.scheme ?? P2ID_SCHEME} has no ${environment} factory address in this release yet; pass \`factory\` explicitly`);
|
|
53
|
+
}
|
|
54
|
+
if (!/^0x[0-9a-fA-F]{40}$/.test(factory))
|
|
55
|
+
throw new Error(`bad factory address ${factory}`);
|
|
56
|
+
const preimage = new Uint8Array(1 + 20 + 32 + 32);
|
|
57
|
+
preimage[0] = 0xff;
|
|
58
|
+
preimage.set(hexToBytes(factory, 20), 1);
|
|
59
|
+
preimage.set(hexToBytes(identityHash, 32), 21);
|
|
60
|
+
preimage.set(hexToBytes(scheme.vaultInitCodeHash, 32), 53);
|
|
61
|
+
return checksumAddress(toHex(keccak_256(preimage).subarray(12)));
|
|
62
|
+
}
|
|
63
|
+
/** EIP-55 checksum. */
|
|
64
|
+
export function checksumAddress(address) {
|
|
65
|
+
const lower = address.slice(2).toLowerCase();
|
|
66
|
+
const hash = keccak_256(new TextEncoder().encode(lower));
|
|
67
|
+
let out = '0x';
|
|
68
|
+
for (let i = 0; i < 40; i++) {
|
|
69
|
+
const nibble = (hash[i >> 1] >> (i % 2 === 0 ? 4 : 0)) & 0xf;
|
|
70
|
+
out += nibble >= 8 ? lower[i].toUpperCase() : lower[i];
|
|
71
|
+
}
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
74
|
+
function hexToBytes(hex, length) {
|
|
75
|
+
const h = hex.startsWith('0x') ? hex.slice(2) : hex;
|
|
76
|
+
if (h.length !== length * 2 || !/^[0-9a-fA-F]*$/.test(h))
|
|
77
|
+
throw new Error(`expected ${length}-byte hex, got ${hex}`);
|
|
78
|
+
const out = new Uint8Array(length);
|
|
79
|
+
for (let i = 0; i < length; i++)
|
|
80
|
+
out[i] = parseInt(h.slice(i * 2, i * 2 + 2), 16);
|
|
81
|
+
return out;
|
|
82
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface P2IDScheme {
|
|
2
|
+
/** Domain prefix of the identity hash this scheme salts vaults with, e.g. "p2id.identity.v1". */
|
|
3
|
+
identityDomain: string;
|
|
4
|
+
/** keccak256 of the P2IDVault creation code; with the factory address it fixes every vault address. */
|
|
5
|
+
vaultInitCodeHash: `0x${string}`;
|
|
6
|
+
/**
|
|
7
|
+
* The PviumP2IdVaultFactory per Pvium environment. Deployed through the deterministic deployment
|
|
8
|
+
* proxy, so within an environment it has one address on every EVM chain. "production" is the
|
|
9
|
+
* mainnet stack, "sandbox" the testnet stack (a different Privy app and key set). Null until
|
|
10
|
+
* that environment's first deployment is recorded.
|
|
11
|
+
*/
|
|
12
|
+
factories: {
|
|
13
|
+
production: `0x${string}` | null;
|
|
14
|
+
sandbox: `0x${string}` | null;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/** Every P2ID address scheme this release can derive, keyed by domain. Older schemes stay forever. */
|
|
18
|
+
export declare const P2ID_SCHEMES: {
|
|
19
|
+
readonly "p2id.vault.v1": {
|
|
20
|
+
readonly identityDomain: "p2id.identity.v1";
|
|
21
|
+
readonly vaultInitCodeHash: "0xe6b8d636ef647cfda0770fa7f2a8c93b886399c3d9405ffcb35ef946083a0802";
|
|
22
|
+
readonly factories: {
|
|
23
|
+
readonly production: null;
|
|
24
|
+
readonly sandbox: "0x21859137b4979B101079742942c741224529eE6D";
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
readonly "p2id.vault.v2": {
|
|
28
|
+
readonly identityDomain: "p2id.identity.v1";
|
|
29
|
+
readonly vaultInitCodeHash: "0xd98f76cb96350f1064d0358ba2d449e80533e26ba3900b7fba5d7570888f3699";
|
|
30
|
+
readonly factories: {
|
|
31
|
+
readonly production: null;
|
|
32
|
+
readonly sandbox: "0x85463cD0FC3CcB9d0891E2ac3124322349A23a86";
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
export type P2IDSchemeName = keyof typeof P2ID_SCHEMES;
|
|
37
|
+
/** The scheme new payments should use. */
|
|
38
|
+
export declare const P2ID_SCHEME: "p2id.vault.v2";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Every P2ID address scheme this release can derive, keyed by domain. Older schemes stay forever. */
|
|
2
|
+
export const P2ID_SCHEMES = {
|
|
3
|
+
"p2id.vault.v1": {
|
|
4
|
+
"identityDomain": "p2id.identity.v1",
|
|
5
|
+
"vaultInitCodeHash": "0xe6b8d636ef647cfda0770fa7f2a8c93b886399c3d9405ffcb35ef946083a0802",
|
|
6
|
+
"factories": {
|
|
7
|
+
"production": null,
|
|
8
|
+
"sandbox": "0x21859137b4979B101079742942c741224529eE6D"
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"p2id.vault.v2": {
|
|
12
|
+
"identityDomain": "p2id.identity.v1",
|
|
13
|
+
"vaultInitCodeHash": "0xd98f76cb96350f1064d0358ba2d449e80533e26ba3900b7fba5d7570888f3699",
|
|
14
|
+
"factories": {
|
|
15
|
+
"production": null,
|
|
16
|
+
"sandbox": "0x85463cD0FC3CcB9d0891E2ac3124322349A23a86"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
/** The scheme new payments should use. */
|
|
21
|
+
export const P2ID_SCHEME = 'p2id.vault.v2';
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pvium/p2id-core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "P2ID protocol core: identity types and hashing, chain-agnostic P2ID address derivation, and the Solidity sources",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/cjs/index.js",
|
|
8
|
+
"module": "./dist/esm/index.js",
|
|
9
|
+
"types": "./dist/esm/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/esm/index.d.ts",
|
|
13
|
+
"import": "./dist/esm/index.js",
|
|
14
|
+
"require": "./dist/cjs/index.js",
|
|
15
|
+
"default": "./dist/esm/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./contracts/*": "./contracts/*"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"contracts",
|
|
22
|
+
"README.md"
|
|
23
|
+
],
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "git+https://github.com/pvium/zkid.git"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "sh scripts/sync-contracts.sh && node scripts/embed-p2id.mjs && tsc -p tsconfig.esm.json && tsc -p tsconfig.cjs.json && node scripts/finalize-dist.mjs",
|
|
30
|
+
"test": "yarn build && node --test --import tsx test/*.test.ts",
|
|
31
|
+
"prepublishOnly": "yarn test"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@noble/hashes": "^1.5.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/node": "^20.0.0",
|
|
38
|
+
"tsx": "^4.19.0",
|
|
39
|
+
"typescript": "^5.0.0"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=20"
|
|
43
|
+
}
|
|
44
|
+
}
|