mirror of
https://github.com/logos-blockchain/logos-blockchain-circuits.git
synced 2026-01-20 05:53:10 +00:00
Merge pull request #7 from logos-blockchain/tl/PoL_update
Tl/po l update
This commit is contained in:
commit
0b0054a57b
@ -221,7 +221,7 @@ if not core_or_leader in [0,1]:
|
||||
# 1) Core‐node registry Merkle‐proof
|
||||
# pick a random core_sk and derive its public key
|
||||
core_sk = F(randrange(0,p,1))
|
||||
pk_core = Compression([ F(1296193216988918402894), core_sk ])
|
||||
pk_core = Compression([ F(4605003), core_sk ])
|
||||
core_selectors = randrange(0,2**20,1)
|
||||
core_selectors = format(int(core_selectors),'020b')
|
||||
core_nodes = [F(randrange(0,p,1)) for i in range(20)]
|
||||
@ -247,30 +247,18 @@ t1 = F(p- (int(t1_constant) // total_stake**2))
|
||||
|
||||
value = F(total_stake / 100)
|
||||
threshold = (t0 + t1 * value) * value
|
||||
starting_slot = randrange(max(0,slot_number-2**25+1),slot_number,1)
|
||||
|
||||
slot_secret = F(randrange(0,p,1))
|
||||
slot_secret_indexes = format(int(slot_number - starting_slot),'025b')
|
||||
|
||||
sk = F(randrange(0,p,1))
|
||||
tx_hash = F(randrange(0,p,1))
|
||||
output_number = F(randrange(0,50,1))
|
||||
|
||||
pk = Compression([F(4605003),sk])
|
||||
|
||||
slot_secret_path = [F(randrange(0,p,1)) for i in range(25)]
|
||||
secret_root = slot_secret
|
||||
for i in range(25):
|
||||
if int(slot_secret_indexes[24-i]) == 0:
|
||||
secret_root = Compression([secret_root,slot_secret_path[i]])
|
||||
else:
|
||||
secret_root = Compression([slot_secret_path[i],secret_root])
|
||||
sk = poseidon2_hash([F(256174383281726064679014503048630094),starting_slot,secret_root])
|
||||
pk = Compression([F(1296193216988918402894),sk])
|
||||
|
||||
note_id = poseidon2_hash([F(65580641562429851895355409762135920462),tx_hash,output_number,value,pk])
|
||||
note_id = poseidon2_hash([F(232989242343357190262606),tx_hash,output_number,value,pk])
|
||||
ticket = poseidon2_hash([F(13887241025832268),F(epoch_nonce),F(slot_number),note_id,sk])
|
||||
while(ticket > threshold):
|
||||
output_number += 1
|
||||
note_id = poseidon2_hash([F(65580641562429851895355409762135920462),tx_hash,output_number,value,pk])
|
||||
note_id = poseidon2_hash([F(232989242343357190262606),tx_hash,output_number,value,pk])
|
||||
ticket = poseidon2_hash([F(13887241025832268),F(epoch_nonce),F(slot_number),note_id,sk])
|
||||
|
||||
aged_nodes = [F(randrange(0,p,1)) for i in range(32)]
|
||||
@ -308,13 +296,11 @@ inp = {
|
||||
"pol_epoch_nonce": str(epoch_nonce),
|
||||
"pol_t0": str(t0),
|
||||
"pol_t1": str(t1),
|
||||
"pol_slot_secret": str(slot_secret),
|
||||
"pol_slot_secret_path": [str(x) for x in slot_secret_path],
|
||||
"pol_secret_key": str(sk),
|
||||
"pol_noteid_path": [str(x) for x in aged_nodes],
|
||||
"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_sk_starting_slot": str(starting_slot),
|
||||
"pol_note_value": str(value)
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
pragma circom 2.1.9;
|
||||
|
||||
include "../hash_bn/poseidon2_hash.circom";
|
||||
include "../misc/constants.circom"; // defines NOMOS_KDF, SELECTION_RANDOMNESS, PROOF_NULLIFIER
|
||||
include "../misc/constants.circom"; // defines KDF, SELECTION_RANDOMNESS, PROOF_NULLIFIER
|
||||
include "../misc/comparator.circom";
|
||||
include "../circomlib/circuits/bitify.circom";
|
||||
include "../mantle/pol_lib.circom"; // defines proof_of_leadership
|
||||
@ -48,15 +48,13 @@ template ProofOfQuota(nLevelsPK, nLevelsPol, bitsQuota) {
|
||||
signal input pol_epoch_nonce;
|
||||
signal input pol_t0;
|
||||
signal input pol_t1;
|
||||
signal input pol_slot_secret;
|
||||
signal input pol_slot_secret_path[nLevelsPol];
|
||||
|
||||
signal input pol_noteid_path[32];
|
||||
signal input pol_noteid_path_selectors[32];
|
||||
signal input pol_secret_key;
|
||||
signal input pol_note_tx_hash;
|
||||
signal input pol_note_output_number;
|
||||
|
||||
signal input pol_sk_starting_slot;
|
||||
signal input pol_note_value;
|
||||
|
||||
|
||||
@ -96,10 +94,6 @@ template ProofOfQuota(nLevelsPK, nLevelsPol, bitsQuota) {
|
||||
would_win.epoch_nonce <== pol_epoch_nonce;
|
||||
would_win.t0 <== pol_t0;
|
||||
would_win.t1 <== pol_t1;
|
||||
would_win.slot_secret <== pol_slot_secret;
|
||||
for (var i = 0; i < nLevelsPol; i++) {
|
||||
would_win.slot_secret_path[i] <== pol_slot_secret_path[i];
|
||||
}
|
||||
for (var i = 0; i < 32; i++) {
|
||||
would_win.aged_nodes[i] <== pol_noteid_path[i];
|
||||
would_win.aged_selectors[i] <== pol_noteid_path_selectors[i];
|
||||
@ -107,7 +101,7 @@ template ProofOfQuota(nLevelsPK, nLevelsPol, bitsQuota) {
|
||||
would_win.aged_root <== pol_ledger_aged;
|
||||
would_win.transaction_hash <== pol_note_tx_hash;
|
||||
would_win.output_number <== pol_note_output_number;
|
||||
would_win.starting_slot <== pol_sk_starting_slot;
|
||||
would_win.secret_key <== pol_secret_key;
|
||||
would_win.value <== pol_note_value;
|
||||
|
||||
// Enforce the selected role is correct
|
||||
|
||||
@ -5,26 +5,12 @@ include "../hash_bn/poseidon2_hash.circom";
|
||||
include "../hash_bn/poseidon2_perm.circom";
|
||||
include "../misc/constants.circom";
|
||||
|
||||
template derive_secret_key(){
|
||||
signal input starting_slot;
|
||||
signal input secrets_root;
|
||||
signal output out;
|
||||
|
||||
component hash = Poseidon2_hash(3);
|
||||
component dst = NOMOS_POL_SK_V1();
|
||||
hash.inp[0] <== dst.out;
|
||||
hash.inp[1] <== starting_slot;
|
||||
hash.inp[2] <== secrets_root;
|
||||
|
||||
out <== hash.out;
|
||||
}
|
||||
|
||||
template derive_public_key(){
|
||||
signal input secret_key;
|
||||
signal output out;
|
||||
|
||||
component hash = Compression();
|
||||
component dst = NOMOS_KDF();
|
||||
component dst = KDF();
|
||||
hash.inp[0] <== dst.out;
|
||||
hash.inp[1] <== secret_key;
|
||||
out <== hash.out;
|
||||
|
||||
@ -228,30 +228,17 @@ t1 = F(p- (int(t1_constant) // total_stake**2))
|
||||
|
||||
value = F(total_stake / 100)
|
||||
threshold = (t0 + t1 * value) * value
|
||||
starting_slot = randrange(max(0,slot_number-2**25+1),slot_number,1)
|
||||
|
||||
slot_secret = F(randrange(0,p,1))
|
||||
slot_secret_indexes = format(int(slot_number - starting_slot),'025b')
|
||||
|
||||
sk = F(randrange(0,p,1))
|
||||
tx_hash = F(randrange(0,p,1))
|
||||
output_number = F(randrange(0,50,1))
|
||||
pk = Compression([F(4605003),sk])
|
||||
|
||||
|
||||
slot_secret_path = [F(randrange(0,p,1)) for i in range(25)]
|
||||
secret_root = slot_secret
|
||||
for i in range(25):
|
||||
if int(slot_secret_indexes[24-i]) == 0:
|
||||
secret_root = Compression([secret_root,slot_secret_path[i]])
|
||||
else:
|
||||
secret_root = Compression([slot_secret_path[i],secret_root])
|
||||
sk = poseidon2_hash([F(256174383281726064679014503048630094),starting_slot,secret_root])
|
||||
pk = Compression([F(1296193216988918402894),sk])
|
||||
|
||||
note_id = poseidon2_hash([F(65580641562429851895355409762135920462),tx_hash,output_number,value,pk])
|
||||
note_id = poseidon2_hash([F(232989242343357190262606),tx_hash,output_number,value,pk])
|
||||
ticket = poseidon2_hash([F(13887241025832268),F(epoch_nonce),F(slot_number),note_id,sk])
|
||||
while(ticket > threshold):
|
||||
output_number += 1
|
||||
note_id = poseidon2_hash([F(65580641562429851895355409762135920462),tx_hash,output_number,value,pk])
|
||||
note_id = poseidon2_hash([F(232989242343357190262606),tx_hash,output_number,value,pk])
|
||||
ticket = poseidon2_hash([F(13887241025832268),F(epoch_nonce),F(slot_number),note_id,sk])
|
||||
|
||||
aged_nodes = [F(randrange(0,p,1)) for i in range(32)]
|
||||
@ -284,10 +271,9 @@ inp = {
|
||||
"epoch_nonce": str(epoch_nonce),
|
||||
"t0": str(t0),
|
||||
"t1": str(t1),
|
||||
"slot_secret": str(slot_secret),
|
||||
"secret_key": str(sk),
|
||||
"P_lead_part_one": str(F(123456)),
|
||||
"P_lead_part_two": str(F(654321)),
|
||||
"slot_secret_path": [str(x) for x in slot_secret_path],
|
||||
"noteid_aged_path": [str(x) for x in aged_nodes],
|
||||
"noteid_aged_selectors": [str(x) for x in aged_selectors],
|
||||
"ledger_aged": str(aged_root),
|
||||
@ -296,7 +282,6 @@ inp = {
|
||||
"noteid_latest_path": [str(x) for x in unspent_nodes],
|
||||
"noteid_latest_selectors": [str(x) for x in unspent_selectors],
|
||||
"ledger_latest": str(latest_root),
|
||||
"starting_slot": str(starting_slot),
|
||||
"v": str(value)
|
||||
}
|
||||
|
||||
|
||||
@ -34,7 +34,7 @@ template derive_entropy(){
|
||||
signal output out;
|
||||
|
||||
component hash = Poseidon2_hash(4);
|
||||
component dst = NOMOS_NONCE_CONTRIB_V1();
|
||||
component dst = NONCE_CONTRIB_V1();
|
||||
hash.inp[0] <== dst.out;
|
||||
hash.inp[1] <== slot;
|
||||
hash.inp[2] <== note_id;
|
||||
@ -48,8 +48,6 @@ template would_win_leadership(secret_depth){
|
||||
signal input epoch_nonce;
|
||||
signal input t0;
|
||||
signal input t1;
|
||||
signal input slot_secret;
|
||||
signal input slot_secret_path[secret_depth];
|
||||
|
||||
//Part of the note id proof of membership to prove aged
|
||||
signal input aged_nodes[32];
|
||||
@ -59,51 +57,23 @@ template would_win_leadership(secret_depth){
|
||||
//Used to derive the note identifier
|
||||
signal input transaction_hash;
|
||||
signal input output_number;
|
||||
|
||||
//Part of the secret key
|
||||
signal input starting_slot;
|
||||
signal input secret_key;
|
||||
|
||||
// The winning note value
|
||||
signal input value;
|
||||
|
||||
signal output out;
|
||||
signal output note_identifier;
|
||||
signal output secret_key;
|
||||
|
||||
|
||||
// Derivation of the secrets root from the slot secret at position slot - starting_slot
|
||||
// Verify that the substraction wont underflow (starting_slot < slot)
|
||||
component checker = SafeFullLessThan();
|
||||
checker.a <== starting_slot;
|
||||
checker.b <== slot;
|
||||
|
||||
// Compute the positions related to slot - starting_slot and make sure slot - starting_slot is a 25 bits number
|
||||
component bits = Num2Bits(secret_depth);
|
||||
bits.in <== slot - starting_slot;
|
||||
|
||||
// Derive the secrets root
|
||||
component secrets_root = compute_merkle_root(secret_depth);
|
||||
for(var i=0; i<secret_depth; i++){
|
||||
secrets_root.nodes[i] <== slot_secret_path[i];
|
||||
secrets_root.selector[i] <== bits.out[secret_depth-1-i];
|
||||
}
|
||||
secrets_root.leaf <== slot_secret;
|
||||
|
||||
|
||||
// Derive the secret key
|
||||
component sk = derive_secret_key();
|
||||
sk.starting_slot <== starting_slot;
|
||||
sk.secrets_root <== secrets_root.root;
|
||||
|
||||
|
||||
// Derive the public key from the secret key
|
||||
component pk = derive_public_key();
|
||||
pk.secret_key <== sk.out;
|
||||
pk.secret_key <== secret_key;
|
||||
|
||||
|
||||
// Derive the note id
|
||||
component note_id = Poseidon2_hash(5);
|
||||
component dst_note_id = NOMOS_NOTE_ID_V1();
|
||||
component dst_note_id = NOTE_ID_V1();
|
||||
note_id.inp[0] <== dst_note_id.out;
|
||||
note_id.inp[1] <== transaction_hash;
|
||||
note_id.inp[2] <== output_number;
|
||||
@ -131,7 +101,7 @@ template would_win_leadership(secret_depth){
|
||||
ticket.epoch_nonce <== epoch_nonce;
|
||||
ticket.slot <== slot;
|
||||
ticket.note_id <== note_id.out;
|
||||
ticket.secret_key <== sk.out;
|
||||
ticket.secret_key <== secret_key;
|
||||
|
||||
|
||||
// Compute the lottery threshold
|
||||
@ -147,12 +117,9 @@ template would_win_leadership(secret_depth){
|
||||
winning.b <== threshold;
|
||||
|
||||
// Check that every constraint holds
|
||||
signal intermediate_out;
|
||||
intermediate_out <== aged_membership.out * winning.out;
|
||||
out <== intermediate_out * checker.out;
|
||||
out <== aged_membership.out * winning.out;
|
||||
|
||||
note_identifier <== note_id.out;
|
||||
secret_key <== sk.out;
|
||||
}
|
||||
|
||||
|
||||
@ -161,8 +128,6 @@ template proof_of_leadership(secret_depth){
|
||||
signal input epoch_nonce; // the epoch nonce eta
|
||||
signal input t0;
|
||||
signal input t1;
|
||||
signal input slot_secret; // This is r_sl
|
||||
signal input slot_secret_path[secret_depth];
|
||||
|
||||
//Part of the note id proof of membership to prove aged
|
||||
signal input noteid_aged_path[32];
|
||||
@ -170,6 +135,7 @@ template proof_of_leadership(secret_depth){
|
||||
signal input ledger_aged;
|
||||
|
||||
//Used to derive the note identifier
|
||||
signal input secret_key;
|
||||
signal input note_tx_hash;
|
||||
signal input note_output_number;
|
||||
|
||||
@ -178,10 +144,7 @@ template proof_of_leadership(secret_depth){
|
||||
signal input noteid_latest_selectors[32]; // must be bits
|
||||
signal input ledger_latest;
|
||||
|
||||
//Part of the secret key
|
||||
signal input starting_slot;
|
||||
|
||||
// The winning note. The unit is supposed to be NMO and the ZoneID is MANTLE
|
||||
// The winning note.
|
||||
signal input v; // value of the note
|
||||
|
||||
|
||||
@ -191,10 +154,6 @@ template proof_of_leadership(secret_depth){
|
||||
lottery_checker.epoch_nonce <== epoch_nonce;
|
||||
lottery_checker.t0 <== t0;
|
||||
lottery_checker.t1 <== t1;
|
||||
lottery_checker.slot_secret <== slot_secret;
|
||||
for(var i = 0; i < secret_depth; i++){
|
||||
lottery_checker.slot_secret_path[i] <== slot_secret_path[i];
|
||||
}
|
||||
for(var i = 0; i < 32; i++){
|
||||
lottery_checker.aged_nodes[i] <== noteid_aged_path[i];
|
||||
lottery_checker.aged_selectors[i] <== noteid_aged_selectors[i];
|
||||
@ -202,7 +161,7 @@ template proof_of_leadership(secret_depth){
|
||||
lottery_checker.aged_root <== ledger_aged;
|
||||
lottery_checker.transaction_hash <== note_tx_hash;
|
||||
lottery_checker.output_number <== note_output_number;
|
||||
lottery_checker.starting_slot <== starting_slot;
|
||||
lottery_checker.secret_key <== secret_key;
|
||||
lottery_checker.value <== v;
|
||||
|
||||
|
||||
@ -241,7 +200,7 @@ template proof_of_leadership(secret_depth){
|
||||
component entropy = derive_entropy();
|
||||
entropy.slot <== sl;
|
||||
entropy.note_id <== lottery_checker.note_identifier;
|
||||
entropy.secret_key <== lottery_checker.secret_key;
|
||||
entropy.secret_key <== secret_key;
|
||||
|
||||
entropy_contribution <== entropy.out;
|
||||
}
|
||||
|
||||
@ -11,31 +11,24 @@ template LEAD_V1(){
|
||||
}
|
||||
|
||||
|
||||
// int.from_bytes(b"NOMOS_POL_SK_V1", byteorder="little") = 256174383281726064679014503048630094
|
||||
template NOMOS_POL_SK_V1(){
|
||||
// int.from_bytes(b"NONCE_CONTRIB_V1", byteorder="little") = 65580641403957881555985426713123114830
|
||||
template NONCE_CONTRIB_V1(){
|
||||
signal output out;
|
||||
out <== 256174383281726064679014503048630094;
|
||||
out <== 65580641403957881555985426713123114830;
|
||||
}
|
||||
|
||||
|
||||
// int.from_bytes(b"NOMOS_NONCE_CONTRIB_V1", byteorder="little") = 18459309511848927313552932915476467038165525790019406
|
||||
template NOMOS_NONCE_CONTRIB_V1(){
|
||||
// int.from_bytes(b"KDF", byteorder="little") = 4605003
|
||||
template KDF(){
|
||||
signal output out;
|
||||
out <== 18459309511848927313552932915476467038165525790019406;
|
||||
out <== 4605003;
|
||||
}
|
||||
|
||||
|
||||
// int.from_bytes(b"NOMOS_KDF", byteorder="little") = 1296193216988918402894
|
||||
template NOMOS_KDF(){
|
||||
// int.from_bytes(b"NOTE_ID_V1", byteorder="little") = 232989242343357190262606
|
||||
template NOTE_ID_V1(){
|
||||
signal output out;
|
||||
out <== 1296193216988918402894;
|
||||
}
|
||||
|
||||
|
||||
// int.from_bytes(b"NOMOS_NOTE_ID_V1", byteorder="little") = 65580641562429851895355409762135920462
|
||||
template NOMOS_NOTE_ID_V1(){
|
||||
signal output out;
|
||||
out <== 65580641562429851895355409762135920462;
|
||||
out <== 232989242343357190262606;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user