empower the poq (#51)

* empower the poq

* update test inputs

* Enhance GMP download process in CI workflow

Updated GMP download step to try multiple URLs with retries.

* revert ci

* fix test

* bump version

* add cargo lock
This commit is contained in:
thomaslavaur 2026-08-04 13:44:26 +02:00 committed by GitHub
parent 61b7e5aa60
commit bd4fe8bad3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 179 additions and 116 deletions

View File

@ -206,15 +206,16 @@ def PoseidonSponge(data, capacity, output_len):
# ———————————————————————
# Main
# ———————————————————————
if len(sys.argv) != 4:
print("Usage: python3 generate_inputs_for_poq.py <core_quota> <leader_quota> <core (0) or leader (1)>")
if len(sys.argv) != 5:
print("Usage: python3 generate_inputs_for_poq.py <core_quota> <leader_quota> <pow_quota> <core (0) or leader (1) or pow (2)>")
sys.exit(1)
Qc = int(sys.argv[1])
Ql = int(sys.argv[2])
core_or_leader = int(sys.argv[3])
if not core_or_leader in [0,1]:
print("core or leader must be 0 or 1")
Qp = int(sys.argv[3])
role_selector = int(sys.argv[4])
if not role_selector in [0,1,2]:
print("core or leader or pow must be 0 or 1 or 2")
sys.exit(1)
# 1) Corenode registry Merkleproof
@ -270,8 +271,18 @@ for i in range(32):
else:
aged_root = Compression([aged_nodes[i],aged_root])
# PoW inputs
pow_block_hash = F(randrange(0,p,1))
pow_sk = F(randrange(0,p,1))
pow_pk = Compression([F(4605003),pow_sk])
pow_ticket = poseidon2_hash([F(epoch_nonce),F(pow_block_hash), F(pow_pk)])
if role_selector == 2:
pow_difficulty = pow_ticket + 1
else:
pow_difficulty = pow_ticket - 1
# 3) Choose branch & index
index = randrange(0, Ql if core_or_leader else Qc,1)
index = randrange(0, Ql if role_selector == 0 else (Qc if role_selector == 1 else Qp),1)
# 4) Onetime key
K_one = F(123456)
@ -281,11 +292,12 @@ K_two = F(654321)
inp = {
"core_quota": str(Qc),
"leader_quota": str(Ql),
"pow_quota": str(Qp),
"core_root": str(core_root),
"pol_ledger_aged": str(aged_root),
"K_part_one": str(K_one),
"K_part_two": str(K_two),
"selector": str(core_or_leader),
"selector": str(role_selector),
"index": str(index),
"core_sk": str(core_sk),
"core_path": [str(x) for x in core_nodes],
@ -299,12 +311,15 @@ inp = {
"pol_noteid_path_selectors": [str(x) for x in aged_selectors],
"pol_note_tx_hash": str(tx_hash),
"pol_note_output_number": str(output_number),
"pol_note_value": str(value)
"pol_note_value": str(value),
"pow_block_hash": str(pow_block_hash),
"pow_blend_difficulty": str(pow_difficulty),
"pow_sk": str(pow_sk)
}
if core_or_leader == 0:
if role_selector != 1:
inp["pol_ledger_aged"] = str(randrange(0,p,1))
else:
if role_selector != 0:
inp["core_root"] = str(randrange(0,p,1))
import json

View File

@ -20,9 +20,12 @@ template ProofOfQuota(nLevelsPK, nLevelsPol, bitsQuota) {
signal input core_quota;
signal input leader_quota;
signal input core_root;
signal input pow_quota;
signal input pol_ledger_aged; // PoL: aged notes root
signal input K_part_one; // Blend: one-time signature public key
signal input K_part_two; // Blend: one-time signature public key
signal input pow_block_hash;
signal input pow_blend_difficulty;
// dummy constraints to avoid unused public input to be erased after compilation optimisation
@ -34,7 +37,7 @@ template ProofOfQuota(nLevelsPK, nLevelsPol, bitsQuota) {
signal output key_nullifier; //key_nullifier
// Private Inputs
signal input selector; // 0 = core, 1 = leader
signal input selector; // 0 = core, 1 = leader, 2 = pow
signal input index; // nullifier index
// Core-nodes inputs
@ -56,15 +59,29 @@ template ProofOfQuota(nLevelsPK, nLevelsPol, bitsQuota) {
signal input pol_note_value;
// Constraint the selector to be a bit
selector * (1 - selector) === 0;
// PoW branch input
signal input pow_sk;
// Quota check: index < core_quota if core, index < leader_quota if leader
// Constraint the selector to be a 0, 1 or 2
signal selector_squared;
selector_squared <== selector * selector;
(selector_squared - selector) * (selector - 2) === 0;
// compute lagrange polynomial for selectors
signal L1;
signal L2;
component inv_2 = INV_2();
L1 <== - selector_squared + 2 * selector;
L2 <== (selector_squared - selector) * inv_2.out;
// Quota check: index < core_quota if core, index < leader_quota if leader, index < pow_quota if pow
signal lh_quota_cmp;
lh_quota_cmp <== (leader_quota - core_quota) * L1;
component cmp = SafeLessThan(bitsQuota);
cmp.in[0] <== index;
cmp.in[1] <== selector * (leader_quota - core_quota) + core_quota;
cmp.in[1] <== core_quota + lh_quota_cmp + (pow_quota - core_quota) * L2;
cmp.out === 1;
@ -103,18 +120,39 @@ template ProofOfQuota(nLevelsPK, nLevelsPol, bitsQuota) {
would_win.secret_key <== pol_secret_key;
would_win.value <== pol_note_value;
// Derive pow pk
signal output pow_pk;
component pow_pk_derivation = derive_public_key();
pow_pk_derivation.secret_key <== pow_sk;
pow_pk <== pow_pk_derivation.out;
// Get the blend PoW result
component pow_ticket = Poseidon2_hash(3);
pow_ticket.inp[0] <== pol_epoch_nonce;
pow_ticket.inp[1] <== pow_block_hash;
pow_ticket.inp[2] <== pow_pk;
component is_winning_pow = SafeFullLessThan();
is_winning_pow.a <== pow_ticket.out;
is_winning_pow.b <== pow_blend_difficulty;
// Enforce the selected role is correct
selector * (would_win.out - is_registered.out) + is_registered.out === 1;
signal lh_correctness_selector;
lh_correctness_selector <== (would_win.out - is_registered.out) * L1;
is_registered.out + lh_correctness_selector + (is_winning_pow.out - is_registered.out) * L2 === 1;
// Derive selection_randomness
component selection_randomness = Poseidon2_hash(4);
component dstSel = SELECTION_RANDOMNESS_V1();
selection_randomness.inp[0] <== dstSel.out;
// choose core_sk or pol.secret_key:
selection_randomness.inp[1] <== selector * (would_win.secret_key - core_sk ) + core_sk;
// choose core_sk, pol.secret_key or pow_sk:
signal lh_key_selector;
lh_key_selector <== (would_win.secret_key - core_sk) * L1;
selection_randomness.inp[1] <== core_sk + lh_key_selector + (pow_sk - core_sk) * L2;
selection_randomness.inp[2] <== index;
selection_randomness.inp[3] <== selector * (would_win.slot - pol_epoch_nonce) + pol_epoch_nonce;
selection_randomness.inp[3] <== pol_epoch_nonce + (would_win.slot - pol_epoch_nonce) * L1; // because the last term is (pol_epoch_nonce - pol_epoch_nonce) * L2 = 0
// Derive key_nullifier
@ -126,5 +164,5 @@ template ProofOfQuota(nLevelsPK, nLevelsPol, bitsQuota) {
}
// Instantiate with chosen depths: 20 for core PK tree, 25 for PoL secret slot tree
component main { public [ core_quota, leader_quota, core_root, K_part_one, K_part_two, pol_epoch_nonce, pol_t0, pol_t1, pol_ledger_aged ] }
component main { public [ core_quota, leader_quota, pow_quota, core_root, K_part_one, K_part_two, pol_epoch_nonce, pol_t0, pol_t1, pol_ledger_aged, pow_block_hash, pow_blend_difficulty] }
= ProofOfQuota(20, 25, 20);

View File

@ -4,6 +4,12 @@ pragma circom 2.1.9;
include "../circomlib/circuits/bitify.circom";
include "../circomlib/circuits/comparators.circom";
// inverse of 2
template INV_2(){
signal output out;
out <== 10944121435919637611123202872628637544274182200208017171849102093287904247809;
}
// int.from_bytes(b"LEAD_V1", byteorder="little") = 13887241025832268
template LEAD_V1(){
signal output out;

18
rust/Cargo.lock generated
View File

@ -181,7 +181,7 @@ checksum = "616ec5685824bcc94416c6d4a7a446eea774a31efd7062c8480ba6fd06d7a6e5"
[[package]]
name = "logos-blockchain-circuits-build"
version = "0.5.3"
version = "0.5.4"
dependencies = [
"dirs",
"fd-lock",
@ -192,14 +192,14 @@ dependencies = [
[[package]]
name = "logos-blockchain-circuits-common"
version = "0.5.3"
version = "0.5.4"
dependencies = [
"logos-blockchain-circuits-types",
]
[[package]]
name = "logos-blockchain-circuits-poc-sys"
version = "0.5.3"
version = "0.5.4"
dependencies = [
"logos-blockchain-circuits-build",
"logos-blockchain-circuits-common",
@ -209,7 +209,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-circuits-pol-sys"
version = "0.5.3"
version = "0.5.4"
dependencies = [
"logos-blockchain-circuits-build",
"logos-blockchain-circuits-common",
@ -219,7 +219,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-circuits-poq-sys"
version = "0.5.3"
version = "0.5.4"
dependencies = [
"logos-blockchain-circuits-build",
"logos-blockchain-circuits-common",
@ -229,14 +229,14 @@ dependencies = [
[[package]]
name = "logos-blockchain-circuits-rapidsnark-sys"
version = "0.5.3"
version = "0.5.4"
dependencies = [
"logos-blockchain-circuits-build",
]
[[package]]
name = "logos-blockchain-circuits-signature-sys"
version = "0.5.3"
version = "0.5.4"
dependencies = [
"logos-blockchain-circuits-build",
"logos-blockchain-circuits-common",
@ -245,7 +245,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-circuits-tests"
version = "0.5.3"
version = "0.5.4"
dependencies = [
"logos-blockchain-circuits-pol-sys",
"logos-blockchain-circuits-poq-sys",
@ -253,7 +253,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-circuits-types"
version = "0.5.3"
version = "0.5.4"
dependencies = [
"bytes",
"libc",

View File

@ -6,7 +6,7 @@ keywords = ["blockchain", "privacy"]
license = "MIT or Apache-2.0"
readme = "README.md"
repository = "https://github.com/logos-blockchain/logos-blockchain-circuits"
version = "0.5.3"
version = "0.5.4"
[workspace]
members = [

View File

@ -1,113 +1,101 @@
{
"core_quota": "1",
"leader_quota": "10",
"core_root": "7358626607131214682586253304523946160071850873054090941932251900116552785280",
"pol_ledger_aged": "17848125288774642501089540435944460903456646006482467944234533252194069877439",
"core_quota": "10",
"leader_quota": "15",
"pow_quota": "20",
"core_root": "2278315351938823802197428436351458964312281563591370830099523042631329930976",
"pol_ledger_aged": "8857608761052519324091319478761760719083791293775955217426078759766699433547",
"K_part_one": "123456",
"K_part_two": "654321",
"selector": "0",
"index": "0",
"core_sk": "5209097897605387010620715638071336554739532569559254565820554506540253382985",
"selector": "2",
"index": "13",
"core_sk": "6491886539892973755849434091823421444402840426417860801084616732878676629516",
"core_path": [
"17752527643973599850200907158162123421789260288064138808502494798954742404252",
"9379040520123190857535767357874915976437372612793835521471488439298616464898",
"11461160392054216243349156621447102558626723421191357594357394425037175166169",
"3182242865768248001269339794622535742230729277933857812114267231466538272261",
"41157462735450030613212285008103098053283605796552310012335933058594828282",
"8898673234425133025293665335457180035350271106069250532827291493857168761759",
"18766378158080024089872252637601531399756739865331521032970871047107782887362",
"14709123862686005445799988261383261045618207742980203024957694596134833354170",
"12539068583558967267354286296156973269525180111643591810825608135058830839617",
"2952140069158700175322849316704490984440476314038184524603021326977347497633",
"19916770065367293705239216606330751387464165697267859810762847788327722568906",
"7948654779419894653933606281103324343210718942161723582735280359580292203550",
"7264791723462141620611889823641111379865151760782616092505714756552728385391",
"4424801921131821282099543195147450132688717583294774094660090715609317256454",
"17802155476919415332620083104640696574649670233080626578708654591914878198079",
"1597726376193255010119909130845298012629844879455812137043558490423866814607",
"10747414478615691590826244547850573302598774066750987081388130509746066651454",
"2488080958694083728975011168315936693544896511710871375745261690957753282778",
"12587207496859064371585343104907844688634654080593414910704311330996345850073",
"9011965812552988689042552183119939764346306368045046136578647356489304004079"
"16871728244744358161745657974960496189023841808923017628564305477635768843186",
"4807895633444282271159280640540594640131141294224593483831499077966870188916",
"7693312882889233609744822703541229377183777048630468326939946368368691713405",
"15100605939761704082332469908875968474370692196972900327278382043399365569494",
"19124079931000681203851589588902506341281329379700259632653877908487527205174",
"10207212190450676348049350505756613807949730022852993442247806045935722624218",
"19314226489948223465940006067008620058365933353314314829720602089357060189108",
"13841053698724512463711353608619157538488497775259348929810048147935103055088",
"10995086972158761375468523695708142158954480439744238648862883245697280277256",
"11019785577896094669708604324376562934343659633713405407029535307548276709911",
"18705031325250665338999547242714998704677407585605466776788616066286904530536",
"10020022155878963410204244574547234938170254076446044243669389336535306205241",
"14689187226469176455206246434204659233597908298346068579768988460114043748228",
"9931707430944795017853819394907228055939898011026232689071774095926706225268",
"6473782013105202581483732547266498131267420859896461396200937351532600404648",
"18568970163903346461899508777970991837950838815974968128422814955452642429511",
"20133451613697416156406519917337237441925034651002400983780095443595938801110",
"20405346913228617698710148496939642518972634482510843858391814822784975858799",
"18511781400506034527722171078787935135193148140955383736096764700859561516140",
"5342682708104862279395182942329013764215099846538335711172340619260698367146"
],
"core_path_selectors": [
"0",
"1",
"0",
"0",
"1",
"1",
"1",
"1",
"1",
"0",
"0",
"1",
"1",
"0",
"0",
"0",
"1",
"0",
"1",
"1",
"0",
"1",
"1",
"1",
"0"
],
"pol_sl": "3013712891",
"pol_epoch_nonce": "8171879639839015143681394409352721472619633422995827998462084091591385426956",
"pol_sl": "746340147",
"pol_epoch_nonce": "2435516955936361511626596574864789019968410762852947269462799555612719421786",
"pol_t0": "148409079361904587837471709956458430342187235603420891378597419711486680",
"pol_t1": "21888242871336145414933615591437256729835795974444825699352339602896135814447",
"pol_secret_key": "6126637502529733622553644490130144254637143551164579001080245009353780575007",
"pol_secret_key": "15474628662904439605666348896810640880604661667290921807169614254281714755916",
"pol_noteid_path": [
"19523824649949991640733122947360702509103041363669816679057385364738421595015",
"12866666617515056434713078270449819897384244639781006359356789833314185927838",
"11625639580345575538484816180557570964945391956488823097035206927083221136468",
"20226255359058832675561975090219300090365857140011178158245766997070168517469",
"18813427405198187795956307215265079090781176499247795858545231544178484217866",
"15766907329056392732794090849724343177841163100119953466631081758056929337948",
"17057158578543256597782968109615591935074658555700581656458754063375286870186",
"21457251238439122598821661852540315218889340232511640285013028985121142979333",
"9128215354950884953309627273828546566295438177920370966436497949954814238497",
"20288706412130899283418094935877773217895597010453936089261773933373007493383",
"12055453394895462303717909161807277467700266603645297853006114217274670515655",
"1880351095200712608342626474768098992025128037897480861848664497268036645889",
"2973403713563861625695098059351335085647761102443779148469958543166054209071",
"4660863892593605241418106640974813915082681670472315847356569438898721198482",
"10903654216970603525134439847801343597200169667399563708733758526237377018871",
"13389260358886784745360395536715767115411755346451908828998142366539206075409",
"370280185919542099068307227941311295572788226727071709701562477680091313056",
"3784132268409681725912464386667280427177972428543216309893364320011234526466",
"13476088136042569917637353606671246226021176584799646402720393180175313805559",
"12770961249095889110301649901401191384192511679656780753566119020016794642155",
"11003304181442192733666619866226916287215837695042295458228063938564974776167",
"19189717042404551802583935432102545049698388880308877895767488888240836031919",
"15591294614531392075874106964998847554065820397346788637176452429094943367699",
"4827378731315067812213685579248590219382039112909765258979828340851280796018",
"6543426291589641158414400854021080125216814111662177895659872749860114321432",
"13837522293851119725630707772117741568041717917918117000070026934483600034622",
"6025729186733182842212217493627090176913471786304421868658591113329060605538",
"251525172609920268281780324534432402935669617032589659964900108178277276778",
"596267738366722809676427452556707976028498742561750319839370279387905290524",
"3943892203924871636006744100492889189566061675558068101719931566368634467516",
"11776765250297403040627918225511998354804920327502786739933006880387064898343",
"15217403801244457874885447650899805327179971643807412929371341251150084200348"
"5705225319633994602094540547635604875938784685248172885714452323826988736499",
"3585192598981244222164480923971973003743668708431283354826675834568296880110",
"20926871851208881661527361429464269740125440491503750090196232755587007318033",
"4097284074368977766996092506833098704228600398562189840376534597040745098346",
"14616648036762717323630685220215142743906372712246234313073021397884127262255",
"7162215598326160171158973959445560016594881433993472811657515111980104963021",
"7808053551376829708451694030911550175968792288581503734776708996461761906157",
"19949583758615183478490909739670807363080511400402393576187271520358104004179",
"18936740296153265280287484814495988210354377617933572097220711909290301944510",
"37242589925946401627036438208140500424993072712431940704877048939149779548",
"28338709140722865022699316601644209036188766583204333535307996491677679313",
"10563300051322630622582751799673246616944430567059887447457373942218368641506",
"14038690422499397215179665143413032546689989038818447477494962902909219717438",
"14442796694440286244647296714002223019514274105715836393166207855384152242220",
"2580632767662503037375839196647306460362426348054647591403641843708827971719",
"15248158898771773370934713773607119075454613438401065437812446610553017861778",
"1187886085813743369157091141387352108116634586295310520620151423761299673091",
"7861298937890192584531787079322552081185756466706900180492933344881687267131",
"18588093836401294157050478650958039907235044755537001342782027437006693512482",
"2572470137603218375720498196273817733765445637870815549662645173792158401296",
"4801664220045168733003621908259724191040360864481670998281596210808921651055",
"13044267273987422651092333199541604459393296549541602563060548937708932281956",
"19726047396705773485284760138557849704745949506995630065307882621473264402943",
"17405639682614968987864586794356012793424917245332432471274968276624543198815",
"6979960803096170483593794433560044791158275470118218605053420891508047506376",
"9861129738760892809312595968045693584242922490433205847971694986573945433083",
"17650732514380812112387019971911411203336062211360889206536690595954141818086",
"17684964925337267578433040517423219067881618720384847292590614532245335894448",
"10852956951509804445120182009925809404306879100158673430290284297050941619026",
"8516586133493406859738809301400430499790336148114406315526365325168033808306",
"11336309663855220340494673018206944925345207270009232718257526882134092028693",
"17108291412284578390601106865690554274773328917128000102849343295581808709926"
],
"pol_noteid_path_selectors": [
"0",
"1",
"0",
"0",
"0",
"0",
"1",
"1",
"1",
"1",
"1",
"0",
"1",
"1",
"1",
"0",
"1",
"0",
"0",
@ -115,7 +103,10 @@
"1",
"0",
"1",
"0",
"1",
"0",
"0",
"1",
"0",
"0",
@ -123,9 +114,22 @@
"1",
"0",
"0",
"0"
"0",
"1",
"1",
"0",
"0",
"0",
"0",
"1",
"0",
"1",
"1"
],
"pol_note_tx_hash": "6762192302225204907638506437779482371825535174735792388658890099668611185173",
"pol_note_output_number": "331",
"pol_note_value": "50"
"pol_note_tx_hash": "19568366039285768184293154992760886293264426766987780470648900770963806011586",
"pol_note_output_number": "1908",
"pol_note_value": "50",
"pow_block_hash": "15182281860372344261501746024387480497202960100586494763821859162204069377005",
"pow_blend_difficulty": "1683039586965484211549639040376899982678658904500933450891282612438711543917",
"pow_sk": "14534280846962555037683924839557340805677898222123306031026367781251347233747"
}

View File

@ -69,7 +69,7 @@ mod tests {
fn test_generate_witness_constraint_violation_returns_err() {
let json = std::fs::read_to_string(&*INPUTS).unwrap();
let mut inputs: serde_json::Value = serde_json::from_str(&json).unwrap();
inputs["core_root"] = serde_json::json!("1");
inputs["core_path_selectors"][0] = serde_json::json!("2");
let input = PoqWitnessInput::new(serde_json::to_string(&inputs).unwrap()).unwrap();
assert!(generate_witness(&input).is_err());
}