ergotree_interpreter/sigma_protocol/
dht_protocol.rs1use super::wscalar::Wscalar;
4use super::ProverMessage;
5use ergo_chain_types::EcPoint;
6use ergotree_ir::serialization::SigmaSerializable;
7
8#[derive(PartialEq, Eq, Debug, Clone)]
10#[cfg_attr(feature = "json", derive(serde::Serialize, serde::Deserialize))]
11#[cfg_attr(feature = "arbitrary", derive(proptest_derive::Arbitrary))]
12pub struct FirstDhTupleProverMessage {
13 #[cfg_attr(feature = "json", serde(rename = "a"))]
14 a: Box<EcPoint>,
15 #[cfg_attr(feature = "json", serde(rename = "b"))]
16 b: Box<EcPoint>,
17}
18
19impl FirstDhTupleProverMessage {
20 pub fn new(a: EcPoint, b: EcPoint) -> Self {
22 Self {
23 a: a.into(),
24 b: b.into(),
25 }
26 }
27}
28
29impl ProverMessage for FirstDhTupleProverMessage {
30 #[allow(clippy::unwrap_used)] fn bytes(&self) -> Vec<u8> {
32 let mut res = self.a.sigma_serialize_bytes().unwrap();
33 res.append(self.b.sigma_serialize_bytes().unwrap().as_mut());
34 res
35 }
36}
37
38#[derive(PartialEq, Eq, Debug, Clone)]
41#[cfg_attr(feature = "arbitrary", derive(proptest_derive::Arbitrary))]
42pub struct SecondDhTupleProverMessage {
43 pub z: Wscalar,
45}
46
47pub mod interactive_prover {
49
50 use std::ops::Mul;
51
52 use super::*;
53 use crate::sigma_protocol::crypto_utils;
54 use crate::sigma_protocol::private_input::DhTupleProverInput;
55 use crate::sigma_protocol::Challenge;
56 use ergotree_ir::sigma_protocol::dlog_group;
57 use ergotree_ir::sigma_protocol::sigma_boolean::ProveDhTuple;
58 use k256::Scalar;
59
60 pub(crate) fn simulate(
65 public_input: &ProveDhTuple,
66 challenge: &Challenge,
67 ) -> (FirstDhTupleProverMessage, SecondDhTupleProverMessage) {
68 use ergo_chain_types::ec_point::exponentiate;
69 let z = dlog_group::random_scalar_in_group_range(crypto_utils::secure_rng());
71
72 let e: Scalar = challenge.clone().into();
74 let minus_e = e.negate();
75 let h_to_z = exponentiate(&public_input.h, &z);
76 let g_to_z = exponentiate(&public_input.g, &z);
77 let u_to_minus_e = exponentiate(&public_input.u, &minus_e);
78 let v_to_minus_e = exponentiate(&public_input.v, &minus_e);
79 let a = g_to_z.mul(&u_to_minus_e);
80 let b = h_to_z.mul(&v_to_minus_e);
81 (
82 FirstDhTupleProverMessage::new(a, b),
83 SecondDhTupleProverMessage { z: z.into() },
84 )
85 }
86
87 pub fn first_message(public_input: &ProveDhTuple) -> (Wscalar, FirstDhTupleProverMessage) {
93 use ergo_chain_types::ec_point::exponentiate;
94 let r = dlog_group::random_scalar_in_group_range(crypto_utils::secure_rng());
95 let a = exponentiate(&public_input.g, &r);
96 let b = exponentiate(&public_input.h, &r);
97 (r.into(), FirstDhTupleProverMessage::new(a, b))
98 }
99
100 pub(crate) fn second_message(
105 private_input: &DhTupleProverInput,
106 rnd: &Wscalar,
107 challenge: &Challenge,
108 ) -> SecondDhTupleProverMessage {
109 let e: Scalar = challenge.clone().into();
110 let ew = e.mul(private_input.w.as_scalar_ref());
112 let z = rnd.as_scalar_ref().add(&ew);
114 SecondDhTupleProverMessage { z: z.into() }
115 }
116
117 #[allow(clippy::many_single_char_names)]
124 pub fn compute_commitment(
125 proposition: &ProveDhTuple,
126 challenge: &Challenge,
127 second_message: &SecondDhTupleProverMessage,
128 ) -> (EcPoint, EcPoint) {
129 let g = proposition.g.clone();
130 let h = proposition.h.clone();
131 let u = proposition.u.clone();
132 let v = proposition.v.clone();
133
134 let z = second_message.z.clone();
135
136 let e: Scalar = challenge.clone().into();
137
138 use ergo_chain_types::ec_point::{exponentiate, inverse};
139
140 let g_to_z = exponentiate(&g, z.as_scalar_ref());
141 let h_to_z = exponentiate(&h, z.as_scalar_ref());
142
143 let u_to_e = exponentiate(&u, &e);
144 let v_to_e = exponentiate(&v, &e);
145
146 let a = g_to_z.mul(&inverse(&u_to_e));
147 let b = h_to_z.mul(&inverse(&v_to_e));
148 (a, b)
149 }
150}