diff --git a/blend/generate_inputs_for_poq.py b/blend/generate_inputs_for_poq.py index c364be6..5f677b8 100644 --- a/blend/generate_inputs_for_poq.py +++ b/blend/generate_inputs_for_poq.py @@ -206,15 +206,16 @@ def PoseidonSponge(data, capacity, output_len): # ——————————————————————— # Main # ——————————————————————— -if len(sys.argv) != 4: - print("Usage: python3 generate_inputs_for_poq.py ") +if len(sys.argv) != 5: + print("Usage: python3 generate_inputs_for_poq.py ") 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) Core‐node registry Merkle‐proof @@ -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) One‐time 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 diff --git a/blend/poq.circom b/blend/poq.circom index 79b19fd..cc8fd98 100644 --- a/blend/poq.circom +++ b/blend/poq.circom @@ -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); diff --git a/misc/constants.circom b/misc/constants.circom index f18d9b3..524898f 100644 --- a/misc/constants.circom +++ b/misc/constants.circom @@ -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; diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 203efa4..e9bc3a8 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -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", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 9cb0698..f96004d 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -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 = [ diff --git a/rust/logos-blockchain-circuits-poq-sys/sample.input.json b/rust/logos-blockchain-circuits-poq-sys/sample.input.json index 1b3de15..265d233 100644 --- a/rust/logos-blockchain-circuits-poq-sys/sample.input.json +++ b/rust/logos-blockchain-circuits-poq-sys/sample.input.json @@ -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" } \ No newline at end of file diff --git a/rust/logos-blockchain-circuits-poq-sys/src/native.rs b/rust/logos-blockchain-circuits-poq-sys/src/native.rs index fcf055a..3bee363 100644 --- a/rust/logos-blockchain-circuits-poq-sys/src/native.rs +++ b/rust/logos-blockchain-circuits-poq-sys/src/native.rs @@ -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()); }