-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathhash6x128.ts
105 lines (88 loc) · 3.34 KB
/
hash6x128.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// IMPORTS
// ================================================================================================
import { instantiateScript, createPrimeField } from '../../index';
import { StarkOptions } from '@guildofweavers/genstark';
import { getMdsMatrix, transpose, getRoundConstants, createHash } from './utils';
import { Logger, inline } from '../../lib/utils';
// POSEIDON PARAMETERS
// ================================================================================================
const modulus = 2n**128n - 9n * 2n**32n + 1n;
const field = createPrimeField(modulus);
const stateWidth = 6;
const fRounds = 8;
const pRounds = 55;
const steps = fRounds + pRounds + 1;
const mds = getMdsMatrix(field, stateWidth);
const roundConstants = transpose(getRoundConstants(field, stateWidth, steps));
const poseidonHash = createHash(field, 5n, fRounds, pRounds, stateWidth);
const result = poseidonHash([1n, 2n, 3n, 4n]);
const roundControls: bigint[] = [];
for (let i = 0; i < fRounds + pRounds; i++) {
if ((i < fRounds / 2) || (i >= fRounds / 2 + pRounds)) {
roundControls.push(1n);
} else {
roundControls.push(0n);
}
}
roundControls.push(0n);
// STARK DEFINITION
// ================================================================================================
const options: StarkOptions = {
hashAlgorithm : 'blake2s256',
extensionFactor : 16,
exeQueryCount : 68,
friQueryCount : 24,
wasm : true
};
const poseidonStark = instantiateScript(Buffer.from(`
define Poseidon6x128 over prime field (${modulus}) {
const mds: ${inline.matrix(mds)};
static roundConstants: [
cycle ${inline.vector(roundConstants[0])},
cycle ${inline.vector(roundConstants[1])},
cycle ${inline.vector(roundConstants[2])},
cycle ${inline.vector(roundConstants[3])},
cycle ${inline.vector(roundConstants[4])},
cycle ${inline.vector(roundConstants[5])}
];
secret input value1: element[2];
secret input value2: element[2];
transition 6 registers {
for each (value1, value2) {
// initialize the execution trace
init {
yield [...value1, ...value2, 0, 0];
}
for steps [1..4, 60..63] {
// full rounds
yield mds # ($r + roundConstants)^5;
}
for steps [5..59] {
// partial rounds
v5 <- ($r5 + roundConstants[5])^5;
yield mds # [...($r[0..4] + roundConstants[0..4]), v5];
}
}
}
enforce 6 constraints {
for all steps {
enforce transition($r) = $n;
}
}
}`), options, new Logger(false));
// TESTING
// ================================================================================================
// set up inputs and assertions
const inputs = [[1n], [2n], [3n], [4n]];
const assertions = [
{ step: steps-1, register: 0, value: result[0] },
{ step: steps-1, register: 1, value: result[1] },
];
// generate a proof
const proof = poseidonStark.prove(assertions, inputs);
console.log('-'.repeat(20));
// verify the proof
poseidonStark.verify(assertions, proof);
console.log('-'.repeat(20));
console.log(`Proof size: ${Math.round(poseidonStark.sizeOf(proof) / 1024 * 100) / 100} KB`);
console.log(`Security level: ${poseidonStark.securityLevel}`)