edit pol with the new shielded and unshielded notes

This commit is contained in:
thomaslavaur 2025-04-10 10:40:20 +02:00
parent 4843f7140d
commit 11b9d06357
3 changed files with 90 additions and 78 deletions

View File

@ -250,40 +250,49 @@ while(ticket > threshold):
note_nonce += 1
note_cm = poseidon2_hash([F(181645510297841241569044198526601622686169271532834574969543446901055041748),state,value,unit,note_nonce,pk,F(363778563868520716613768381832117227806204156179492995214325445980623358665)])
ticket = poseidon2_hash([F(137836078329650723736739065075984465408055658421620421917147974048265460598),F(epoch_nonce),F(slot_number),note_cm,sk])
cm_aged_nodes = [F(randrange(0,p,1)) for i in range(32)]
cm_aged_selectors = randrange(0,2**32,1)
cm_aged_selectors = format(cm_aged_selectors,'032b')
tx_hash = F(randrange(0,p,1))
output_number = F(randrange(0,4,1))
note_id = poseidon2_hash([F(342101038445105569972307194441697646307927876218883552376182649811837164915),tx_hash,output_number,note_cm])
aged_nodes = [F(randrange(0,p,1)) for i in range(32)]
aged_selectors = randrange(0,2**32,1)
aged_selectors = format(aged_selectors,'032b')
cm_aged_root = note_cm
for i in range(32):
if int(cm_aged_selectors[31-i]) == 0:
cm_aged_root = poseidon2_hash([cm_aged_root,cm_aged_nodes[i]])
if int(aged_selectors[31-i]) == 0:
cm_aged_root = poseidon2_hash([cm_aged_root,aged_nodes[i]])
else:
cm_aged_root = poseidon2_hash([cm_aged_nodes[i],cm_aged_root])
cm_aged_root = poseidon2_hash([aged_nodes[i],cm_aged_root])
cm_unspent_nodes = [F(randrange(0,p,1)) for i in range(32)]
cm_unspent_selectors = randrange(0,2**32,1)
cm_unspent_selectors = format(cm_unspent_selectors,'032b')
cm_unspent_root = note_cm
note_id_aged_root = note_id
for i in range(32):
if int(cm_unspent_selectors[31-i]) == 0:
cm_unspent_root = poseidon2_hash([cm_unspent_root,cm_unspent_nodes[i]])
if int(aged_selectors[31-i]) == 0:
note_id_aged_root = poseidon2_hash([note_id_aged_root,aged_nodes[i]])
else:
cm_unspent_root = poseidon2_hash([cm_unspent_nodes[i],cm_unspent_root])
note_id_aged_root = poseidon2_hash([aged_nodes[i],note_id_aged_root])
unspent_nodes = [F(randrange(0,p,1)) for i in range(32)]
unspent_selectors = randrange(0,2**32,1)
unspent_selectors = format(unspent_selectors,'032b')
note_id_unspent_root = note_id
for i in range(32):
if int(unspent_selectors[31-i]) == 0:
note_id_unspent_root = poseidon2_hash([note_id_unspent_root,unspent_nodes[i]])
else:
note_id_unspent_root = poseidon2_hash([unspent_nodes[i],note_id_unspent_root])
note_nf = poseidon2_hash([F(310945536431723660304787929213143698356852257431717126117833288836338828411),note_cm,sk])
nf_previous = F(randrange(0,note_nf,1))
nf_next = F(randrange(note_nf+1,p,1))
nf_nodes = [F(randrange(0,p,1)) for i in range(32)]
nf_selectors = randrange(0,2**32,1)
nf_selectors = format(nf_selectors,'032b')
nf_root = poseidon2_hash([nf_previous, nf_next])
for i in range(32):
if int(nf_selectors[31-i]) == 0:
nf_root = poseidon2_hash([nf_root,nf_nodes[i]])
if int(unspent_selectors[31-i]) == 0:
nf_root = poseidon2_hash([nf_root,unspent_nodes[i]])
else:
nf_root = poseidon2_hash([nf_nodes[i],nf_root])
nf_root = poseidon2_hash([unspent_nodes[i],nf_root])
with open("input.json", "w") as file:
file.write('{\n\t"slot":\t\t\t\t\t\t"'+str(slot_number)+'",')
@ -305,66 +314,49 @@ with open("input.json", "w") as file:
file.write('],')
else:
file.write(',')
file.write('\n\t"cm_aged_nodes" :\t\t\t\t\t[')
file.write('\n\t"aged_nodes" :\t\t\t\t\t[')
for i in range(32):
file.write('"')
file.write(str(cm_aged_nodes[i]))
file.write(str(aged_nodes[i]))
file.write('"')
if i == 31:
file.write('],')
else:
file.write(',')
file.write('\n\t"cm_aged_selectors" :\t\t\t\t\t[')
file.write('\n\t"aged_selectors" :\t\t\t\t\t[')
for i in range(32):
file.write('"')
file.write(str(cm_aged_selectors[i]))
file.write(str(aged_selectors[i]))
file.write('"')
if i == 31:
file.write('],')
else:
file.write(',')
file.write('\n\t"commitments_aged_root" :\t\t\t\t"'+str(cm_aged_root)+'",')
file.write('\n\t"note_id_aged_root" :\t\t\t\t"'+str(note_id_aged_root)+'",')
file.write('\n\t"transaction_hash" :\t\t\t\t"'+str(tx_hash)+'",')
file.write('\n\t"output_number" :\t\t\t\t"'+str(output_number)+'",')
file.write('\n\t"nf_previous" :\t\t\t\t"'+str(nf_previous)+'",')
file.write('\n\t"nf_next" :\t\t\t\t"'+str(nf_next)+'",')
if anonymity == "public":
file.write('\n\t"unspent_nodes" :\t\t\t\t\t[')
for i in range(32):
file.write('"')
file.write(str(cm_unspent_nodes[i]))
file.write('"')
if i == 31:
file.write('],')
else:
file.write(',')
file.write('\n\t"unspent_selectors" :\t\t\t\t\t[')
for i in range(32):
file.write('"')
file.write(str(cm_unspent_selectors[i]))
file.write('"')
if i == 31:
file.write('],')
else:
file.write(',')
file.write('\n\t"cm_unspent_root" :\t\t\t\t"'+str(cm_unspent_root)+'",')
if anonymity == "private":
file.write('\n\t"unspent_nodes" :\t\t\t\t\t[')
for i in range(32):
file.write('"')
file.write(str(nf_nodes[i]))
file.write('"')
if i == 31:
file.write('],')
else:
file.write(',')
file.write('\n\t"unspent_selectors" :\t\t\t\t\t[')
for i in range(32):
file.write('"')
file.write(str(nf_selectors[i]))
file.write('"')
if i == 31:
file.write('],')
else:
file.write(',')
file.write('\n\t"unspent_nodes" :\t\t\t\t\t[')
for i in range(32):
file.write('"')
file.write(str(unspent_nodes[i]))
file.write('"')
if i == 31:
file.write('],')
else:
file.write(',')
file.write('\n\t"unspent_selectors" :\t\t\t\t\t[')
for i in range(32):
file.write('"')
file.write(str(unspent_selectors[i]))
file.write('"')
if i == 31:
file.write('],')
else:
file.write(',')
file.write('\n\t"note_id_unspent_root" :\t\t\t\t"'+str(note_id_unspent_root)+'",')
file.write('\n\t"nf_unspent_root" :\t\t\t\t"'+str(nf_root)+'",')
file.write('\n\t"starting_slot" :\t\t\t\t"'+str(starting_slot)+'",')
file.write('\n\t"secrets_root" :\t\t\t\t"'+str(secret_root)+'",')

View File

@ -58,7 +58,7 @@ template derive_entropy(){
template proof_of_leadership(){
signal input selector; // 0 if the note is private and 1 if the note is public
signal input selector; // 0 if the note is shielded and 1 if the note is unshielded
// Check that the selector is indeed a bit
selector * (1- selector) === 0;
@ -70,11 +70,17 @@ template proof_of_leadership(){
signal input slot_secret;
signal input slot_secret_path[25];
//Part of the commitment proof of membership to prove aged
signal input cm_aged_nodes[32];
signal input cm_aged_selectors[32]; // must be bits
//Part of the commitment or note id proof of membership to prove aged
signal input aged_nodes[32];
signal input aged_selectors[32]; // must be bits
signal input commitments_aged_root;
signal input note_id_aged_root;
//Used to derive the note identifier, it can be dumb inputs if it's a shielded note
signal input transaction_hash;
signal input output_number;
//Part of the nullifer proof of non-membership/commitment proof of membership to prove the note is unspent
signal input nf_previous; // Can be mocked and set to any value if selector == 1 as long as previous < nullifier < next
@ -82,7 +88,7 @@ template proof_of_leadership(){
signal input unspent_nodes[32];
signal input unspent_selectors[32]; // must be bits
signal input nf_unspent_root;
signal input cm_unspent_root;
signal input note_id_unspent_root;
//Part of the secret key
signal input starting_slot;
@ -131,19 +137,27 @@ template proof_of_leadership(){
nf.secret_key <== sk.out;
// Derive the note id
component note_id = Poseidon2_hash(4);
component dst_note_id = NOMOS_NOTE_ID();
note_id.inp[0] <== dst_note_id.out;
note_id.inp[1] <== transaction_hash;
note_id.inp[2] <== output_number;
note_id.inp[3] <== cm.out;
// Check commitment membership (is aged enough)
//First check selectors are indeed bits
for(var i = 0; i < 32; i++){
cm_aged_selectors[i] * (1 - cm_aged_selectors[i]) === 0;
aged_selectors[i] * (1 - aged_selectors[i]) === 0;
}
//Then check the proof of membership
component cm_aged_membership = proof_of_membership(32);
component aged_membership = proof_of_membership(32);
for(var i = 0; i < 32; i++){
cm_aged_membership.nodes[i] <== cm_aged_nodes[i];
cm_aged_membership.selector[i] <== cm_aged_selectors[i];
aged_membership.nodes[i] <== aged_nodes[i];
aged_membership.selector[i] <== aged_selectors[i];
}
cm_aged_membership.root <== commitments_aged_root;
cm_aged_membership.leaf <== cm.out;
aged_membership.root <== (note_id_aged_root - commitments_aged_root) * selector + commitments_aged_root;
aged_membership.leaf <== (note_id.out - cm.out) * selector + cm.out;
// Compute the lottery ticket
@ -173,18 +187,18 @@ template proof_of_leadership(){
for(var i = 0; i < 32; i++){
unspent_selectors[i] * (1 - unspent_selectors[i]) === 0;
}
//Then check the proof of membership (that the nullifier leaf is in the set or that the commitment is)
//Then check the proof of membership (that the nullifier leaf is in the set or that the note identifier is)
component unspent_membership = proof_of_membership(32);
for(var i = 0; i < 32; i++){
unspent_membership.nodes[i] <== unspent_nodes[i];
unspent_membership.selector[i] <== unspent_selectors[i];
}
unspent_membership.root <== (cm_unspent_root - nf_unspent_root) * selector + nf_unspent_root;
unspent_membership.root <== (note_id_unspent_root - nf_unspent_root) * selector + nf_unspent_root;
//Compute the leaf if it's a private note representing previous nf pointing to next in the IMT
component hash = Poseidon2_hash(2);
hash.inp[0] <== nf_previous;
hash.inp[1] <== nf_next;
unspent_membership.leaf <== (cm.out - hash.out) * selector + hash.out; // the leaf is then either the commitment or the leaf computed before
unspent_membership.leaf <== (note_id.out - hash.out) * selector + hash.out; // the leaf is then either the note identifier or the leaf computed before
// Check that nullifier stictly falls between previous and next if the note is private.
// If the note is public previous and next can be any values such that previous < nullifier < next
@ -227,4 +241,4 @@ template proof_of_leadership(){
entropy_contrib <== entropy.out;
}
component main {public [slot,epoch_nonce,t0,t1,commitments_aged_root,nf_unspent_root,cm_unspent_root,one_time_key]}= proof_of_leadership();
component main {public [slot,epoch_nonce,t0,t1,commitments_aged_root,note_id_aged_root,nf_unspent_root,note_id_unspent_root,one_time_key]}= proof_of_leadership();

View File

@ -71,4 +71,10 @@ template NOMOS_UNIT(){
template NMO(){
signal output out;
out <== 19676183153323264216568033390884511718872104179761154996527087027500271872825;
}
// int.from_bytes(hashlib.sha256(b"NOMOS_NOTE_ID").digest()[:-1], "little") = 342101038445105569972307194441697646307927876218883552376182649811837164915
template NOMOS_NOTE_ID(){
signal output out;
out <== 342101038445105569972307194441697646307927876218883552376182649811837164915;
}