-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #58 from 0xPolygonHermez/feature/climb-key-const-tool
add tool to verify climb_key constants, add verification doc
- Loading branch information
Showing
2 changed files
with
290 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
# ClimbKey (constants) | ||
|
||
Goldilocks = **0xFFFFFFFF00000001** | ||
Chunks = 18 bits, 18 bits, 18 bits, 10 bits (LSB => MSB) | ||
GoldilocksChunks[4] = [0x00001, 0x3C000, 0x3FFFF, 0x3FF] | ||
0xFFFFFFFF00000001 == 0x00001 + 2**18 * 0x3C000 + 2 **36 * 0x3FFFF + 2 ** 54 * 0x3FF | ||
|
||
*carry* and *lt* are after apply shift and set climb bit | ||
*lt* is done only with bits of chunk | ||
*carryLt* = *carry* + 2 * *lt* | ||
|
||
*cols* = CLKSEL, CARRY_LT_IN, CARRY_LT_OUT, CHUNK_RANGE, LEVELS | ||
*climb* = (CHUNK_RANGE * 2 + bit) & CHUNK_MASK | ||
*glc* = goldilocks chunk | ||
|
||
CLKSEL = CLK + 4 * selKey0 + 8 * selKey1 + 16 * selKey2 + 32 * selKey3 | ||
[a1,a2..+..an] arithmetic serie with values = a1, a2, a2 + (a2-a1), a2 + 2*(a2-a1),..,an | ||
|
||
values of *cols* generated with *tools/climb_key/cpp_helpers.js* parsing output of *buildConstants*. | ||
|
||
## CLK0 GL_CHUNK = 0x00001 | ||
|
||
#### clock = 0, bit = 0 (carryLtIn = 0) | ||
valid chunk values (all) = 0x0, 0x1-0x1ffff, 0x20000, 0x20001-0x3ffff | ||
|cols(*) |climb|glc|notes| | ||
|------|-------|---|----| | ||
|0,0,**2**,0x0,0|0x0|0x00001|ltOut = 1 (only for chunk = 0) ⇒ carryLtOut = 2| | ||
|0,0,**0**,0x1-0x1ffff,0|0x2-0x3fffe|0x00001|ltOut = 0, carryOut = 0 ⇒ carryLtOut = 0| | ||
|0,0,**3**,0x20000,0|0x00000|0x00001|ltOut = 1, carryOut = 1 ⇒ carryLtOut = 3 (1)| | ||
|0,0,**1**,0x20001-0x3ffff,0|0x00001-0x3fffe|0x00001|ltOut = 0, carryOut = 1 ⇒ carryLtOut = 2| | ||
|
||
(1) lt is active because ((0x20000 << 1) & 0x3FFFF) = 0 | ||
|
||
#### clock = 0, bit = 1 (carryLtIn = 1) | ||
valid chunk values (all) = 0x0-0x1ffff, 0x20000-0x3ffff | ||
|
||
|cols(*) |climb|glc|notes| | ||
|------|-------|---|----| | ||
|0,1,0,0x0-0x1ffff,0|0x1-0x3ffff|0x00001|ltOut = 0, carryOut = 0 ⇒ carryLtOut = 0| | ||
|0,1,1,0x20000-0x3ffff,0|0x1-0x3ffff|0x00001|ltOut = 0, carryOut = 1 ⇒ carryLtOut = 1| | ||
|
||
## CLK1 GL_CHUNK = 0x3C000 | ||
|
||
#### clock = 1, carryIn = 0, ltIn = 0 (carryLtIn = 0) | ||
valid chunk values (all) = 0x0-0x1dfff, 0x1e000-0x1ffff, 0x20000-0x3dfff, 0x3e000-0x3ffff | ||
|
||
|cols(*) |climb|glc|notes| | ||
|------|-------|---|----| | ||
|1,0,2,0x0-0x1dfff,0|0x0-0x3bffe(1)|0x3c00|carryOut = 0 ltOut = 1 ⇒ carryLtOut = 2 | | ||
|1,0,0,0x1e000-0x1ffff,0|0x3c000-0x3fffe|0x3c00|carryOut = 0 ltOut = 0 ⇒ carryLtOut = 0| | ||
|1,0,3,0x20000-0x3dfff,0|0x0-0x3bffe|0x3c00|carryOut = 1 ltOut = 1 ⇒ carryLtOut = 3| | ||
|1,0,1,0x3e000-0x3ffff,0|0x3c000-0x3fffe|0x3c00|carryOut = 1 ltOut = 0 ⇒ carryLtOut = 1| | ||
|
||
(1) 0x3bfff not included because after shift LSB is zero | ||
|
||
#### clock = 1, carryIn = 1, ltIn = 0 (carryLtIn = 1) | ||
valid chunk values (all) = 0x0-0x1dfff, 0x1e000-0x1ffff, 0x20000-0x3dfff, 0x3e000-0x3ffff | ||
|
||
|cols(*) |climb|glc|notes| | ||
|------|-------|---|----| | ||
|1,1,2,0x0-0x1dfff,0|0x1-0x3bfff|0x3c000|carryOut = 0 ltOut = 1 ⇒ carryLtOut = 2| | ||
|1,1,0,0x1e000-0x1ffff,0|0x3c001-0x3ffff|0x3c000|carryOut = 0 ltOut = 0 ⇒ carryLtOut = 0| | ||
|1,1,3,0x20000-0x3dfff,0|0x1-0x3dfff|0x3c000|carryOut = 1 ltOut = 1 ⇒ carryLtOut = 3| | ||
|1,1,1,0x3e000-0x3ffff,0|0x3c001-0x3ffff|0x3c000|carryOut = 1 ltOut = 0 ⇒ carryLtOut = 2| | ||
|
||
#### clock = 1, carryIn = 0, ltIn = 1 (carryLtIn = 2) | ||
valid chunk values (all) = 0x0-0x1e000, 0x1e001-0x1ffff, 0x20000-0x3e000, 0x3e001-0x3ffff | ||
|
||
|cols(*) |climb|glc|notes| | ||
|------|-------|---|----| | ||
|1,2,2,0x0,0|0x0|0x3c000|carryOut = 0 ltOut = 1 ⇒ carryLtOut = 2 (1)| | ||
|1,2,2,0x0-0x1e000,0|0x0-0x3c000|0x3c000|carryOut = 0 ltOut = 1 ⇒ carryLtOut = 2| | ||
|1,2,0,0x1e001-0x1ffff,0|0x3c002-3fffe|0x3c000|carryOut = 0 ltOut = 0 ⇒ carryLtOut = 0| | ||
|1,2,3,0x20000-0x3e000,0|0x0-3c000|0x3c000|carryOut = 1 ltOut = 1 ⇒ carryLtOut = 3| | ||
|1,2,1,0x3e001-0x3ffff,0|0x3c002-0x3fffe|0x3c000|carryOut = 1 ltOut = 0 ⇒ carryLtOut = 1| | ||
|
||
(1) specific case at begining of table for empty rows | ||
|
||
#### clock = 1, carryIn = 1, ltIn = 1 (carryLtIn = 3) | ||
valid chunk values (all) = 0x0-0x1dfff, 0x1e000-0x1ffff, 0x20000-0x3dfff, 0x3e000-0x3ffff | ||
|
||
|cols(*) |climb|glc|notes| | ||
|------|-------|---|----| | ||
|1,3,2,0x0-0x1dfff,0|0x1-0x3bfff|0x3c000|carryOut = 0 ltOut = 1 ⇒ carryLtOut = 2| | ||
|1,3,0,0x1e000-0x1ffff,0|0x3c001-0x3ffff|0x3c000|carryOut = 0 ltOut = 0 ⇒ carryLtOut = 0| | ||
|1,3,3,0x20000-0x3dfff,0|0x1-0x3bfff|0x3c000|carryOut = 1 ltOut = 1 ⇒ carryLtOut = 3| | ||
|1,3,1,0x3e000-0x3ffff,0|0x3c001-0x3ffff|0x3c000|carryOut = 1 ltOut = 0 ⇒ carryLtOut = 1| | ||
|
||
## CLK2 GL_CHUNK = 0x3FFFF | ||
|
||
#### clock = 2, carryIn = 0, ltIn = 0 (carryLtIn = 0) | ||
valid chunk values (all) = 0x0-0x1ffff, 0x20000-0x3ffff | ||
|
||
|cols(*) |climb|glc|notes| | ||
|------|-------|---|----| | ||
|2,0,2,0x0-0x1ffff,0|0x0-0x3fffe|0x3ffff|carryOut = 0 ltOut = 1 ⇒ carryLtOut = 2| | ||
|2,0,3,0x20000-0x3ffff,0|0x0-0x3fffe|0x3ffff|carryOut = 1 ltOut = 1 ⇒ carryLtOut = 3| | ||
|
||
#### clock = 2, carryIn = 1, ltIn = 0 (carryLtIn = 1) | ||
valid chunk values (all) = 0x0-0x1fffe, 0x1ffff, 0x20000-0x3fffe, 0x3ffff | ||
|
||
|cols(*) |climb|glc|notes| | ||
|------|-------|---|----| | ||
|2,1,2,0x0-0x1fffe,0|0x1-0x3fffd|0x3ffff|carryOut = 0 ltOut = 1 ⇒ carryLtOut = 2| | ||
|2,1,0,0x1ffff,0|0x3ffff|0x3ffff|carryOut = 0 ltOut = 0 ⇒ carryLtOut = 0| | ||
|2,1,3,0x20000-0x3fffe,0|0x1-0x3fffd|0x3ffff|carryOut = 1 ltOut = 1 ⇒ carryLtOut = 3| | ||
|2,1,1,0x3ffff,0|0x3ffff|0x3ffff|carryOut = 1 ltOut = 0 ⇒ carryLtOut = 1| | ||
|
||
#### clock = 2, carryIn = 0, ltIn = 1 (carryLtIn = 2) | ||
valid chunk values (all) = 0x0-0x1ffff, 0x20000-0x3ffff | ||
|
||
|cols(*) |climb|glc|notes| | ||
|------|-------|---|----| | ||
|2,2,2,0x0|0x0|0x3ffff|carryOut = 0 ltOut = 1 ⇒ carryLtOut = 2| | ||
|2,2,2,0x0-0x1ffff,0|0x0-0x3fffe|0x3ffff|carryOut = 0 ltOut = 1 ⇒ carryLtOut = 2| | ||
|2,2,3,0x20000-0x3ffff,0|0x0-0x3fffe|0x3ffff|carryOut = 1 ltOut = 1 ⇒ carryLtOut = 3| | ||
|
||
#### clock = 2, carryIn = 1, ltIn = 1 (carryLtIn = 3) | ||
valid chunk values (all) = 0x0-0x1ffff, 0x20000-0x3ffff | ||
|
||
|cols(*) |climb|glc|notes| | ||
|------|-------|---|----| | ||
|2,3,2,0x0-0x1ffff,0|0x0-0x3ffff|0x3ffff|carryOut = 0 ltOut = 1 ⇒ carryLtOut = 2| | ||
|2,3,3,0x20000-0x3ffff,0|0x1-0x3ffff|0x3ffff|carryOut = 1 ltOut = 0 ⇒ carryLtOut = 3| | ||
|
||
## CLK3 GL_CHUNK = 0x3FF | ||
In this clock all carryOut = 0 and ltOut = 1 otherwise key is greater o equal goldilocks, and it means invalid key (not include in lockup table) | ||
|
||
#### clock = 3 carryIn = 0, ltIn = 0 (carryLtIn = 0) | ||
valid chunk values (all) = 0x0-0x1ff | ||
0x1ff * 2 + 0 = 0x3fe < 0x3ff ⇒ OK !! | ||
|
||
|cols(*) |climb|glc|notes| | ||
|------|-------|---|----| | ||
|7,0,0,0x0-0x1ff,[0,4..+..252]|0x0-0x3fe|0x3ff|level % 4 == 0 ⇒ selKey0 = 1| | ||
|11,0,0,0x0-0x1ff,[1,5..+..253]|0x0-0x3fe|0x3ff|level % 4 == 1 ⇒ selKey1 = 1| | ||
|19,0,0,0x0-0x1ff,[2,6..+..254]|0x0-0x3fe|0x3ff|level % 4 == 2 ⇒ selKey2 = 1| | ||
|35,0,0,0x0-0x1ff,[3,7..+..255]|0x0-0x3fe|0x3ff|level % 4 == 3 ⇒ selKey3 = 1| | ||
|
||
#### clock = 3 carryIn = 1, ltIn = 0 (carryLtIn = 1) | ||
valid chunk values (all) = 0x0-0x1fe | ||
0x1fe * 2 + 1 = 0x3fd < 0x3ff ⇒ OK !! | ||
0x1ff * 2 + 1 = 0x3ff == 0x3ff && ltIn = 0 ⇒ FAILS !! | ||
|
||
|cols(*) |climb|glc|notes| | ||
|------|-------|---|----| | ||
|7,1,0,0x0-0x1fe,[0,4..+..252]|0x1-0x3fd|0x3ff|level % 4 = 0 ⇒ selKey0 = 1| | ||
|11,1,0,0x0-0x1fe,[1,5..+..253]|0x1-0x3fd|0x3ff|level % 4 = 1 ⇒ selKey1 = 1| | ||
|19,1,0,0x0-0x1fe,[2,6..+..254]|0x1-0x3fd|0x3ff|level % 4 = 2 ⇒ selKey2 = 1| | ||
|35,1,0,0x0-0x1fe,[3,7..+..255]|0x1-0x3fd|0x3ff|level % 4 = 3 ⇒ selKey3 = 1| | ||
|
||
#### clock = 3 carryIn = 0, ltIn = 1 (carryLtIn = 2) | ||
valid chunk values (all) = 0x0-0x1ff | ||
0x1ff * 2 + 0 = 0x3fe < 0x3ff ⇒ OK !! | ||
|
||
|cols(*) |climb|glc|notes| | ||
|------|-------|---|----| | ||
|7,2,0,0x0-0x0,0|0x0-0x3fe|0x3ff|level = 0 ⇒ selKey0 = 1| | ||
|7,2,0,0x0-0x1ff,[0,4..+..252]|0x0-0x3fe|0x3ff|level % 4 = 0 ⇒ selKey0 = 1| | ||
|11,2,0,0x0-0x1ff,[1,5..+..253]|0x0-0x3fe|0x3ff|level % 4 = 1 ⇒ selKey1 = 1| | ||
|19,2,0,0x0-0x1ff,[2,6..+..254]|0x0-0x3fe|0x3ff|level % 4 = 2 ⇒ selKey2 = 1| | ||
|35,2,0,0x0-0x1ff,[3,7..+..255]|0x0-0x3fe|0x3ff|level % 4 = 3 ⇒ selKey3 = 1| | ||
|
||
|
||
#### clock = 3 carryIn = 1, ltIn = 1 (carryLtIn = 3) | ||
valid chunk values (all) = 0x0-0x1ff | ||
0x1fe * 2 + 1 = 0x3fd < 0x3ff ⇒ OK !! | ||
0x1ff * 2 + 1 = 0x3ff == 0x3ff && ltIn = 1 ⇒ OK !! | ||
|
||
|cols(*) |climb|glc|notes| | ||
|------|-------|---|----| | ||
|7,3,0,0x0-0x1ff,[0,4..+..252]|0x1-0x3ff|0x3ff|level % 4 = 0 => selKey0 = 1| | ||
|11,3,0,0x0-0x1ff,[1,5..+..253]|0x1-0x3ff|0x3ff|level % 4 = 1 => selKey1 = 1| | ||
|19,3,0,0x0-0x1ff,[2,6..+..254]|0x1-0x3ff|0x3ff|level % 4 = 2 => selKey2 = 1| | ||
|35,3,0,0x0-0x1ff,[3,7..+..255]|0x1-0x3ff|0x3ff|level % 4 = 3 => selKey3 = 1| |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
const fs = require("fs"); | ||
const path = require("path"); | ||
const tty = require('tty'); | ||
const version = require("../../package").version; | ||
|
||
const chai = require("chai"); | ||
const assert = chai.assert; | ||
const expect = chai.expect; | ||
const F1Field = require("ffjavascript").F1Field; | ||
const util = require('util'); | ||
|
||
const { newConstantPolsArray, newCommitPolsArray, compile, verifyPil } = require("pilcom"); | ||
const smClimbKey = require("../../src/sm/sm_climb_key.js"); | ||
|
||
const argv = require("yargs") | ||
.version(version) | ||
.usage("main_buildconstants -r <rom.json> -o <constant.bin|json> [-p <main.pil>] [-P <pilconfig.json>] [-v]") | ||
.alias("r", "rom") | ||
.alias("o", "output") | ||
.alias("t", "text") | ||
.alias("p", "pil") | ||
.alias("P", "pilconfig") | ||
.alias("v", "verbose") | ||
.argv; | ||
|
||
const DEBUG = false; | ||
|
||
async function run() { | ||
const F = new F1Field("0xFFFFFFFF00000001"); | ||
const pilCode = ` | ||
include "pil/global.pil"; | ||
include "pil/climb_key.pil"; | ||
`; | ||
|
||
const pil = await compile(F, pilCode, null, { compileFromString: true, defines: {N: 2 ** 22}}); | ||
const constPols = newConstantPolsArray(pil); | ||
const pols = constPols.ClimbKey; | ||
|
||
await smClimbKey.buildConstants(pols); | ||
|
||
// T_CLKEYSEL, T_LEVEL, T_CHUNK_VALUE, T_CARRYLT_IN, T_CARRYLT_OUT => "T_CLKEYSEL,T_LEVEL,T_CARRYLT_IN, T_CARRYLT_OUT", FROM_T_CHUNK_VALUE, TO_T_CHUNK_VALUE | ||
|
||
const N = pols.T_CLKEYSEL.length; | ||
let _cols = false; | ||
let _colvalues = []; | ||
let _fromChunkValue = false; | ||
let _toChunkValue = false; | ||
let _row = false; | ||
let groups = []; | ||
let _level = false; | ||
let cols ; | ||
|
||
for (let row = 0; row <= N; ++row) { | ||
if (DEBUG && row < N) { | ||
console.log('ROW#'+row+' '+[pols.T_CLKEYSEL[row], pols.T_CARRYLT_IN[row], pols.T_CARRYLT_OUT[row], pols.T_LEVEL[row], pols.T_CHUNK_VALUE[row].toString(16)].join(',')); | ||
} | ||
const colvalues = (row < N) ? [pols.T_CLKEYSEL[row], pols.T_CARRYLT_IN[row], pols.T_CARRYLT_OUT[row], pols.T_LEVEL[row]] : false; | ||
const cols = colvalues === false ? false : colvalues.join(','); | ||
if (_cols === false) { | ||
_cols = cols; | ||
_colvalues = [...colvalues]; | ||
_row = row; | ||
} else if (_cols !== cols) { | ||
groups.push({cols: _cols, chunk: _fromChunkValue == _toChunkValue ? [_fromChunkValue] : [_fromChunkValue, _toChunkValue], colvalues: [..._colvalues], label: `[${_row}..${row-1}] ${cols} ${Math.round((_row*10000)/N)/100}%`}); | ||
_fromChunkValue = false; | ||
_toChunkValue = false; | ||
_cols = cols; | ||
_colvalues = [...colvalues]; | ||
_row = row; | ||
} | ||
// Check end of loop, after that repeat sequence. | ||
if (_level > 0 && pols.T_LEVEL[row] === 0n) { | ||
break; | ||
} | ||
_level = Number(pols.T_LEVEL[row]); | ||
if (_fromChunkValue === false || _fromChunkValue > pols.T_CHUNK_VALUE[row]) { | ||
_fromChunkValue = pols.T_CHUNK_VALUE[row]; | ||
} | ||
if (_toChunkValue === false || _toChunkValue < pols.T_CHUNK_VALUE[row]) { | ||
_toChunkValue = pols.T_CHUNK_VALUE[row]; | ||
} | ||
} | ||
if (DEBUG) console.log("{\n" + groups.map(x => `\t\t{"${x.cols}", ${x.chunk.map(x => '0x'+x.toString(16)).join('-')}, ${x.colvalues.slice(0, 3).join(',')}}, // ${x.label}`).join("\n") + '\n};'); | ||
let common3 = {}; | ||
groups.map(x => { | ||
let ckey = [...x.colvalues.slice(0, 3),x.chunk.map(x => '0x'+x.toString(16)).join('-')].join(); | ||
if (!common3[ckey]) { | ||
common3[ckey] = []; | ||
} | ||
common3[ckey].push(x.colvalues[3]); | ||
return x.colvalues.join(','); | ||
}); | ||
for (const key in common3) { | ||
const levels = common3[key]; | ||
if (levels.length == 1 || (levels.length == 2 && levels[0] == levels[1])) { | ||
common3[key] = levels[0].toString(); | ||
continue; | ||
} | ||
let clevel = levels[0]; | ||
if (levels.every(level => {const _clevel = clevel; clevel += 4n; return level === _clevel;})) { | ||
common3[key] = levels[0] + ',' + levels[1] + '..+..' + levels.slice(-1)[0]; | ||
} | ||
} | ||
for (const key in common3) { | ||
console.log(key+','+common3[key]); | ||
} | ||
} | ||
|
||
run().then(()=> { | ||
process.exit(0); | ||
}, (err) => { | ||
console.log(err.message); | ||
console.log(err.stack); | ||
process.exit(1); | ||
}); |