1use std::collections::BTreeMap;
8use std::fmt;
9
10use serde::{Deserialize, Serialize};
11use stoffel_vm_types::core_types::ShareType;
12
13use crate::config::MpcBackend;
14use crate::error::{Error, Result};
15
16pub type PartyId = usize;
17pub type ClientId = stoffelnet::network_utils::ClientId;
18pub type Round = stoffel_mpc_coordinator_shared::Round;
19pub type MaskIndex = u64;
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
23#[serde(rename_all = "snake_case")]
24pub enum ClientValueType {
25 Integer,
26 Boolean,
27 FixedPoint,
28}
29
30impl ClientValueType {
31 pub fn is_compatible_with_share_type(self, share_type: ShareType) -> bool {
32 match (self, share_type) {
33 (ClientValueType::Boolean, ShareType::SecretInt { bit_length: 1 }) => true,
34 (ClientValueType::Integer, ShareType::SecretInt { bit_length }) => bit_length > 1,
35 (ClientValueType::Integer, ShareType::SecretUInt { .. }) => true,
36 (ClientValueType::FixedPoint, ShareType::SecretFixedPoint { .. }) => true,
37 _ => false,
38 }
39 }
40}
41
42pub trait ClientInputValue {
44 const VALUE_TYPE: ClientValueType;
45
46 fn into_sdk_value(self) -> Value;
47}
48
49pub trait ClientOutputValue: Sized {
51 const VALUE_TYPE: ClientValueType;
52
53 fn try_from_sdk_value(value: Value) -> Result<Self>;
54}
55
56pub trait TypedClientInputs {
62 fn into_values(self) -> Vec<Value>;
63
64 fn value_types() -> Vec<ClientValueType>;
65}
66
67pub trait TypedClientOutputs: Sized {
72 fn from_values(values: Vec<Value>) -> Result<Self>;
73
74 fn value_types() -> Vec<ClientValueType>;
75}
76
77pub trait ProgramArgs {
91 fn into_values(self) -> Vec<Value>;
92}
93
94pub trait GeneratedProgramManifest {
102 const BACKEND: MpcBackend;
103
104 fn client_input_types(client_slot: u64) -> Option<&'static [ClientValueType]>;
105
106 fn client_output_types(client_slot: u64) -> Option<&'static [ClientValueType]>;
107}
108
109#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
111pub enum Value {
112 I64(i64),
113 U64(u64),
114 Bool(bool),
115 Float(f64),
116 String(String),
117 Bytes(Vec<u8>),
118 List(Vec<Value>),
119 Object(BTreeMap<String, Value>),
120 Unit,
121}
122
123#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
124pub struct ValueSummary {
125 pub kind: String,
126 pub item_count: Option<usize>,
127 pub byte_len: Option<usize>,
128}
129
130impl Value {
131 pub fn kind(&self) -> &'static str {
132 match self {
133 Value::I64(_) => "i64",
134 Value::U64(_) => "u64",
135 Value::Bool(_) => "bool",
136 Value::Float(_) => "float",
137 Value::String(_) => "string",
138 Value::Bytes(_) => "bytes",
139 Value::List(_) => "list",
140 Value::Object(_) => "object",
141 Value::Unit => "unit",
142 }
143 }
144
145 pub fn summary(&self) -> ValueSummary {
146 ValueSummary {
147 kind: self.kind().to_owned(),
148 item_count: match self {
149 Value::List(values) => Some(values.len()),
150 Value::Object(fields) => Some(fields.len()),
151 _ => None,
152 },
153 byte_len: match self {
154 Value::Bytes(bytes) => Some(bytes.len()),
155 Value::String(value) => Some(value.len()),
156 _ => None,
157 },
158 }
159 }
160
161 pub fn as_i64(&self) -> Option<i64> {
162 match self {
163 Value::I64(value) => Some(*value),
164 _ => None,
165 }
166 }
167
168 pub fn as_u64(&self) -> Option<u64> {
169 match self {
170 Value::U64(value) => Some(*value),
171 _ => None,
172 }
173 }
174
175 pub fn as_bool(&self) -> Option<bool> {
176 match self {
177 Value::Bool(value) => Some(*value),
178 _ => None,
179 }
180 }
181
182 pub fn as_f64(&self) -> Option<f64> {
183 match self {
184 Value::Float(value) => Some(*value),
185 _ => None,
186 }
187 }
188
189 pub fn as_str(&self) -> Option<&str> {
190 match self {
191 Value::String(value) => Some(value),
192 _ => None,
193 }
194 }
195
196 pub fn as_bytes(&self) -> Option<&[u8]> {
197 match self {
198 Value::Bytes(value) => Some(value),
199 _ => None,
200 }
201 }
202
203 pub fn as_list(&self) -> Option<&[Value]> {
204 match self {
205 Value::List(values) => Some(values),
206 _ => None,
207 }
208 }
209
210 pub fn as_object(&self) -> Option<&BTreeMap<String, Value>> {
211 match self {
212 Value::Object(fields) => Some(fields),
213 _ => None,
214 }
215 }
216
217 pub fn is_unit(&self) -> bool {
218 matches!(self, Value::Unit)
219 }
220
221 pub fn into_string(self) -> Option<String> {
222 match self {
223 Value::String(value) => Some(value),
224 _ => None,
225 }
226 }
227
228 pub fn into_bytes(self) -> Option<Vec<u8>> {
229 match self {
230 Value::Bytes(value) => Some(value),
231 _ => None,
232 }
233 }
234
235 pub fn into_list(self) -> Option<Vec<Value>> {
236 match self {
237 Value::List(values) => Some(values),
238 _ => None,
239 }
240 }
241
242 pub fn into_object(self) -> Option<BTreeMap<String, Value>> {
243 match self {
244 Value::Object(fields) => Some(fields),
245 _ => None,
246 }
247 }
248
249 pub(crate) fn from_vm_value(value: stoffel_vm_types::core_types::Value) -> Option<Self> {
250 match value {
251 stoffel_vm_types::core_types::Value::I64(value) => Some(Value::I64(value)),
252 stoffel_vm_types::core_types::Value::I32(value) => Some(Value::I64(i64::from(value))),
253 stoffel_vm_types::core_types::Value::I16(value) => Some(Value::I64(i64::from(value))),
254 stoffel_vm_types::core_types::Value::I8(value) => Some(Value::I64(i64::from(value))),
255 stoffel_vm_types::core_types::Value::U64(value) => Some(Value::U64(value)),
256 stoffel_vm_types::core_types::Value::U32(value) => Some(Value::U64(u64::from(value))),
257 stoffel_vm_types::core_types::Value::U16(value) => Some(Value::U64(u64::from(value))),
258 stoffel_vm_types::core_types::Value::U8(value) => Some(Value::U64(u64::from(value))),
259 stoffel_vm_types::core_types::Value::Bool(value) => Some(Value::Bool(value)),
260 stoffel_vm_types::core_types::Value::Float(value) => Some(Value::Float(value.value())),
261 stoffel_vm_types::core_types::Value::String(value) => Some(Value::String(value)),
262 stoffel_vm_types::core_types::Value::Unit => Some(Value::Unit),
263 _ => None,
264 }
265 }
266}
267
268impl fmt::Display for Value {
269 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
270 match self {
271 Value::I64(value) => write!(f, "{value}"),
272 Value::U64(value) => write!(f, "{value}"),
273 Value::Bool(value) => write!(f, "{value}"),
274 Value::Float(value) => write!(f, "{value}"),
275 Value::String(value) => write!(f, "{value}"),
276 Value::Bytes(value) => write!(f, "0x{}", hex_encode(value)),
277 Value::List(values) => {
278 write!(f, "[")?;
279 for (index, value) in values.iter().enumerate() {
280 if index > 0 {
281 write!(f, ", ")?;
282 }
283 write!(f, "{value}")?;
284 }
285 write!(f, "]")
286 }
287 Value::Object(fields) => {
288 write!(f, "{{")?;
289 for (index, (name, value)) in fields.iter().enumerate() {
290 if index > 0 {
291 write!(f, ", ")?;
292 }
293 write!(f, "{name}: {value}")?;
294 }
295 write!(f, "}}")
296 }
297 Value::Unit => write!(f, "()"),
298 }
299 }
300}
301
302fn hex_encode(bytes: &[u8]) -> String {
303 const HEX: &[u8; 16] = b"0123456789abcdef";
304 let mut out = String::with_capacity(bytes.len() * 2);
305 for byte in bytes {
306 out.push(HEX[(byte >> 4) as usize] as char);
307 out.push(HEX[(byte & 0x0f) as usize] as char);
308 }
309 out
310}
311
312macro_rules! value_from_int {
313 ($($ty:ty),* $(,)?) => {
314 $(
315 impl From<$ty> for Value {
316 fn from(value: $ty) -> Self {
317 Value::I64(value as i64)
318 }
319 }
320 )*
321 };
322}
323
324value_from_int!(i8, i16, i32, i64, isize);
325
326macro_rules! value_from_uint {
327 ($($ty:ty),* $(,)?) => {
328 $(
329 impl From<$ty> for Value {
330 fn from(value: $ty) -> Self {
331 Value::U64(value as u64)
332 }
333 }
334 )*
335 };
336}
337
338value_from_uint!(u8, u16, u32, u64, usize);
339
340macro_rules! client_integer_input {
341 ($($ty:ty),* $(,)?) => {
342 $(
343 impl ClientInputValue for $ty {
344 const VALUE_TYPE: ClientValueType = ClientValueType::Integer;
345
346 fn into_sdk_value(self) -> Value {
347 Value::from(self)
348 }
349 }
350 )*
351 };
352}
353
354client_integer_input!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize);
355
356impl From<bool> for Value {
357 fn from(value: bool) -> Self {
358 Value::Bool(value)
359 }
360}
361
362impl ClientInputValue for bool {
363 const VALUE_TYPE: ClientValueType = ClientValueType::Boolean;
364
365 fn into_sdk_value(self) -> Value {
366 Value::Bool(self)
367 }
368}
369
370impl From<f64> for Value {
371 fn from(value: f64) -> Self {
372 Value::Float(value)
373 }
374}
375
376impl ClientInputValue for f64 {
377 const VALUE_TYPE: ClientValueType = ClientValueType::FixedPoint;
378
379 fn into_sdk_value(self) -> Value {
380 Value::Float(self)
381 }
382}
383
384impl From<f32> for Value {
385 fn from(value: f32) -> Self {
386 Value::Float(f64::from(value))
387 }
388}
389
390impl ClientInputValue for f32 {
391 const VALUE_TYPE: ClientValueType = ClientValueType::FixedPoint;
392
393 fn into_sdk_value(self) -> Value {
394 Value::Float(f64::from(self))
395 }
396}
397
398impl From<&str> for Value {
399 fn from(value: &str) -> Self {
400 Value::String(value.to_owned())
401 }
402}
403
404impl From<&String> for Value {
405 fn from(value: &String) -> Self {
406 Value::String(value.clone())
407 }
408}
409
410impl From<String> for Value {
411 fn from(value: String) -> Self {
412 Value::String(value)
413 }
414}
415
416impl From<BTreeMap<String, Value>> for Value {
417 fn from(value: BTreeMap<String, Value>) -> Self {
418 Value::Object(value)
419 }
420}
421
422impl From<&[u8]> for Value {
423 fn from(value: &[u8]) -> Self {
424 Value::Bytes(value.to_vec())
425 }
426}
427
428impl<const N: usize> From<[u8; N]> for Value {
429 fn from(value: [u8; N]) -> Self {
430 Value::Bytes(value.to_vec())
431 }
432}
433
434impl From<Vec<u8>> for Value {
435 fn from(value: Vec<u8>) -> Self {
436 Value::Bytes(value)
437 }
438}
439
440impl From<Vec<Value>> for Value {
441 fn from(value: Vec<Value>) -> Self {
442 Value::List(value)
443 }
444}
445
446impl From<()> for Value {
447 fn from((): ()) -> Self {
448 Value::Unit
449 }
450}
451
452fn value_type_error(expected: &'static str, actual: &Value) -> Error {
453 Error::InvalidInput(format!(
454 "expected {expected} SDK value, got {}",
455 actual.kind()
456 ))
457}
458
459macro_rules! try_from_value_copy {
460 ($target:ty, $variant:ident, $expected:literal) => {
461 impl TryFrom<Value> for $target {
462 type Error = Error;
463
464 fn try_from(value: Value) -> Result<Self> {
465 <$target>::try_from(&value)
466 }
467 }
468
469 impl TryFrom<&Value> for $target {
470 type Error = Error;
471
472 fn try_from(value: &Value) -> Result<Self> {
473 match value {
474 Value::$variant(value) => Ok(*value),
475 actual => Err(value_type_error($expected, actual)),
476 }
477 }
478 }
479 };
480}
481
482try_from_value_copy!(f64, Float, "float");
483
484macro_rules! try_from_signed_integer_value {
485 ($($target:ty),* $(,)?) => {
486 $(
487 impl TryFrom<Value> for $target {
488 type Error = Error;
489
490 fn try_from(value: Value) -> Result<Self> {
491 <$target>::try_from(&value)
492 }
493 }
494
495 impl TryFrom<&Value> for $target {
496 type Error = Error;
497
498 fn try_from(value: &Value) -> Result<Self> {
499 match value {
500 Value::I64(value) => <$target>::try_from(*value).map_err(|_| {
501 Error::InvalidInput(format!("{value} is out of range for {}", stringify!($target)))
502 }),
503 Value::U64(value) => <$target>::try_from(*value).map_err(|_| {
504 Error::InvalidInput(format!("{value} is out of range for {}", stringify!($target)))
505 }),
506 actual => Err(value_type_error(stringify!($target), actual)),
507 }
508 }
509 }
510 )*
511 };
512}
513
514macro_rules! try_from_unsigned_integer_value {
515 ($($target:ty),* $(,)?) => {
516 $(
517 impl TryFrom<Value> for $target {
518 type Error = Error;
519
520 fn try_from(value: Value) -> Result<Self> {
521 <$target>::try_from(&value)
522 }
523 }
524
525 impl TryFrom<&Value> for $target {
526 type Error = Error;
527
528 fn try_from(value: &Value) -> Result<Self> {
529 match value {
530 Value::U64(value) => <$target>::try_from(*value).map_err(|_| {
531 Error::InvalidInput(format!("{value} is out of range for {}", stringify!($target)))
532 }),
533 Value::I64(value) => <$target>::try_from(*value).map_err(|_| {
534 Error::InvalidInput(format!("{value} is out of range for {}", stringify!($target)))
535 }),
536 actual => Err(value_type_error(stringify!($target), actual)),
537 }
538 }
539 }
540 )*
541 };
542}
543
544try_from_signed_integer_value!(i8, i16, i32, i64);
545try_from_unsigned_integer_value!(u8, u16, u32, u64);
546
547impl TryFrom<Value> for bool {
548 type Error = Error;
549
550 fn try_from(value: Value) -> Result<Self> {
551 bool::try_from(&value)
552 }
553}
554
555impl TryFrom<&Value> for bool {
556 type Error = Error;
557
558 fn try_from(value: &Value) -> Result<Self> {
559 match value {
560 Value::Bool(value) => Ok(*value),
561 Value::U64(0) | Value::I64(0) => Ok(false),
562 Value::U64(1) | Value::I64(1) => Ok(true),
563 actual => Err(value_type_error("bool or integer 0/1", actual)),
564 }
565 }
566}
567
568macro_rules! client_integer_output {
569 ($($ty:ty),* $(,)?) => {
570 $(
571 impl ClientOutputValue for $ty {
572 const VALUE_TYPE: ClientValueType = ClientValueType::Integer;
573
574 fn try_from_sdk_value(value: Value) -> Result<Self> {
575 <$ty>::try_from(value)
576 }
577 }
578 )*
579 };
580}
581
582client_integer_output!(i8, i16, i32, i64, u8, u16, u32, u64);
583
584impl ClientOutputValue for bool {
585 const VALUE_TYPE: ClientValueType = ClientValueType::Boolean;
586
587 fn try_from_sdk_value(value: Value) -> Result<Self> {
588 bool::try_from(value)
589 }
590}
591
592impl ClientOutputValue for f64 {
593 const VALUE_TYPE: ClientValueType = ClientValueType::FixedPoint;
594
595 fn try_from_sdk_value(value: Value) -> Result<Self> {
596 f64::try_from(value)
597 }
598}
599
600impl TypedClientInputs for () {
601 fn into_values(self) -> Vec<Value> {
602 Vec::new()
603 }
604
605 fn value_types() -> Vec<ClientValueType> {
606 Vec::new()
607 }
608}
609
610impl ProgramArgs for () {
611 fn into_values(self) -> Vec<Value> {
612 Vec::new()
613 }
614}
615
616impl<T> TypedClientInputs for T
617where
618 T: ClientInputValue,
619{
620 fn into_values(self) -> Vec<Value> {
621 vec![self.into_sdk_value()]
622 }
623
624 fn value_types() -> Vec<ClientValueType> {
625 vec![T::VALUE_TYPE]
626 }
627}
628
629macro_rules! program_arg_scalar {
630 ($($ty:ty),* $(,)?) => {
631 $(
632 impl ProgramArgs for $ty {
633 fn into_values(self) -> Vec<Value> {
634 vec![self.into()]
635 }
636 }
637 )*
638 };
639}
640
641program_arg_scalar!(
642 i8, i16, i32, i64, isize,
643 u8, u16, u32, u64, usize,
644 bool, f32, f64,
645 String, &str, Value,
646 Vec<u8>, &[u8], Vec<Value>, BTreeMap<String, Value>,
647);
648
649impl<const N: usize> ProgramArgs for [u8; N] {
650 fn into_values(self) -> Vec<Value> {
651 vec![self.into()]
652 }
653}
654
655impl ProgramArgs for &String {
656 fn into_values(self) -> Vec<Value> {
657 vec![self.into()]
658 }
659}
660
661impl TypedClientOutputs for () {
662 fn from_values(values: Vec<Value>) -> Result<Self> {
663 if values.is_empty() {
664 Ok(())
665 } else {
666 Err(Error::InvalidInput(format!(
667 "expected 0 typed outputs, got {}",
668 values.len()
669 )))
670 }
671 }
672
673 fn value_types() -> Vec<ClientValueType> {
674 Vec::new()
675 }
676}
677
678impl<T> TypedClientOutputs for T
679where
680 T: ClientOutputValue,
681{
682 fn from_values(values: Vec<Value>) -> Result<Self> {
683 let [value]: [Value; 1] = values.try_into().map_err(|values: Vec<Value>| {
684 Error::InvalidInput(format!("expected 1 typed output, got {}", values.len()))
685 })?;
686 T::try_from_sdk_value(value)
687 }
688
689 fn value_types() -> Vec<ClientValueType> {
690 vec![T::VALUE_TYPE]
691 }
692}
693
694macro_rules! typed_client_tuple {
695 ($(($($type_name:ident $value_name:ident),+)),+ $(,)?) => {
696 $(
697 impl<$($type_name),+> TypedClientInputs for ($($type_name,)+)
698 where
699 $($type_name: ClientInputValue),+
700 {
701 fn into_values(self) -> Vec<Value> {
702 let ($($value_name,)+) = self;
703 vec![$($value_name.into_sdk_value()),+]
704 }
705
706 fn value_types() -> Vec<ClientValueType> {
707 vec![$($type_name::VALUE_TYPE),+]
708 }
709 }
710
711 impl<$($type_name),+> TypedClientOutputs for ($($type_name,)+)
712 where
713 $($type_name: ClientOutputValue),+
714 {
715 fn from_values(values: Vec<Value>) -> Result<Self> {
716 let expected = Self::value_types().len();
717 let actual = values.len();
718 if actual != expected {
719 return Err(Error::InvalidInput(format!(
720 "expected {expected} typed outputs, got {actual}"
721 )));
722 }
723 let mut values = values.into_iter();
724 Ok((
725 $(
726 $type_name::try_from_sdk_value(values.next().expect("length checked"))?,
727 )+
728 ))
729 }
730
731 fn value_types() -> Vec<ClientValueType> {
732 vec![$($type_name::VALUE_TYPE),+]
733 }
734 }
735
736 impl<$($type_name),+> ProgramArgs for ($($type_name,)+)
737 where
738 $($type_name: Into<Value>),+
739 {
740 fn into_values(self) -> Vec<Value> {
741 let ($($value_name,)+) = self;
742 vec![$($value_name.into()),+]
743 }
744 }
745 )+
746 };
747}
748
749typed_client_tuple!(
750 (A a, B b),
751 (A a, B b, C c),
752 (A a, B b, C c, D d),
753 (A a, B b, C c, D d, E e),
754 (A a, B b, C c, D d, E e, F f),
755 (A a, B b, C c, D d, E e, F f, G g),
756 (A a, B b, C c, D d, E e, F f, G g, H h),
757);
758
759impl TryFrom<Value> for String {
760 type Error = Error;
761
762 fn try_from(value: Value) -> Result<Self> {
763 match value {
764 Value::String(value) => Ok(value),
765 actual => Err(value_type_error("string", &actual)),
766 }
767 }
768}
769
770impl TryFrom<&Value> for String {
771 type Error = Error;
772
773 fn try_from(value: &Value) -> Result<Self> {
774 match value {
775 Value::String(value) => Ok(value.clone()),
776 actual => Err(value_type_error("string", actual)),
777 }
778 }
779}
780
781impl<'a> TryFrom<&'a Value> for &'a str {
782 type Error = Error;
783
784 fn try_from(value: &'a Value) -> Result<Self> {
785 match value {
786 Value::String(value) => Ok(value),
787 actual => Err(value_type_error("string", actual)),
788 }
789 }
790}
791
792impl TryFrom<Value> for Vec<u8> {
793 type Error = Error;
794
795 fn try_from(value: Value) -> Result<Self> {
796 match value {
797 Value::Bytes(value) => Ok(value),
798 actual => Err(value_type_error("bytes", &actual)),
799 }
800 }
801}
802
803impl TryFrom<&Value> for Vec<u8> {
804 type Error = Error;
805
806 fn try_from(value: &Value) -> Result<Self> {
807 match value {
808 Value::Bytes(value) => Ok(value.clone()),
809 actual => Err(value_type_error("bytes", actual)),
810 }
811 }
812}
813
814impl<'a> TryFrom<&'a Value> for &'a [u8] {
815 type Error = Error;
816
817 fn try_from(value: &'a Value) -> Result<Self> {
818 match value {
819 Value::Bytes(value) => Ok(value),
820 actual => Err(value_type_error("bytes", actual)),
821 }
822 }
823}
824
825impl TryFrom<Value> for Vec<Value> {
826 type Error = Error;
827
828 fn try_from(value: Value) -> Result<Self> {
829 match value {
830 Value::List(values) => Ok(values),
831 actual => Err(value_type_error("list", &actual)),
832 }
833 }
834}
835
836impl<'a> TryFrom<&'a Value> for &'a [Value] {
837 type Error = Error;
838
839 fn try_from(value: &'a Value) -> Result<Self> {
840 match value {
841 Value::List(values) => Ok(values),
842 actual => Err(value_type_error("list", actual)),
843 }
844 }
845}
846
847impl TryFrom<Value> for () {
848 type Error = Error;
849
850 fn try_from(value: Value) -> Result<Self> {
851 match value {
852 Value::Unit => Ok(()),
853 actual => Err(value_type_error("unit", &actual)),
854 }
855 }
856}
857
858impl TryFrom<&Value> for () {
859 type Error = Error;
860
861 fn try_from(value: &Value) -> Result<Self> {
862 match value {
863 Value::Unit => Ok(()),
864 actual => Err(value_type_error("unit", actual)),
865 }
866 }
867}
868
869#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
870pub struct Share {
871 pub key_name: String,
872 #[serde(default, skip_serializing_if = "Option::is_none")]
873 pub data: Option<Vec<u8>>,
874 #[serde(default, skip_serializing_if = "Vec::is_empty")]
875 pub commitments: Vec<Vec<u8>>,
876}
877
878impl Share {
879 pub fn new(key_name: impl Into<String>) -> Self {
880 Self {
881 key_name: key_name.into(),
882 data: None,
883 commitments: Vec::new(),
884 }
885 }
886
887 pub fn opaque(key_name: impl Into<String>, data: impl Into<Vec<u8>>) -> Self {
888 Self {
889 key_name: key_name.into(),
890 data: Some(data.into()),
891 commitments: Vec::new(),
892 }
893 }
894
895 pub fn feldman(
896 key_name: impl Into<String>,
897 data: impl Into<Vec<u8>>,
898 commitments: impl IntoIterator<Item = impl Into<Vec<u8>>>,
899 ) -> Self {
900 Self {
901 key_name: key_name.into(),
902 data: Some(data.into()),
903 commitments: commitments.into_iter().map(Into::into).collect(),
904 }
905 }
906
907 pub fn key_name(&self) -> &str {
908 &self.key_name
909 }
910
911 pub fn data(&self) -> Option<&[u8]> {
912 self.data.as_deref()
913 }
914
915 pub fn commitments(&self) -> &[Vec<u8>] {
916 &self.commitments
917 }
918
919 pub fn commitment(&self, index: usize) -> Option<&[u8]> {
920 self.commitments.get(index).map(Vec::as_slice)
921 }
922
923 pub fn commitment_count(&self) -> usize {
924 self.commitments.len()
925 }
926
927 pub fn has_commitments(&self) -> bool {
928 !self.commitments.is_empty()
929 }
930
931 pub fn is_feldman(&self) -> bool {
932 self.has_commitments()
933 }
934
935 pub fn is_opaque(&self) -> bool {
936 !self.has_commitments()
937 }
938
939 pub fn public_key(&self) -> Option<PublicKey> {
940 self.commitment(0)
941 .map(|bytes| PublicKey::new(self.key_name.clone(), bytes.to_vec()))
942 }
943}
944
945#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
946pub struct PublicKey {
947 pub key_name: String,
948 pub bytes: Vec<u8>,
949}
950
951impl PublicKey {
952 pub fn new(key_name: impl Into<String>, bytes: impl Into<Vec<u8>>) -> Self {
953 Self {
954 key_name: key_name.into(),
955 bytes: bytes.into(),
956 }
957 }
958
959 pub fn key_name(&self) -> &str {
960 &self.key_name
961 }
962
963 pub fn as_bytes(&self) -> &[u8] {
964 &self.bytes
965 }
966
967 pub fn into_bytes(self) -> Vec<u8> {
968 self.bytes
969 }
970}
971
972#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
973pub struct FieldElement(pub Vec<u8>);
974
975impl FieldElement {
976 pub fn from_bytes(bytes: impl Into<Vec<u8>>) -> Self {
977 Self(bytes.into())
978 }
979
980 pub fn as_bytes(&self) -> &[u8] {
981 &self.0
982 }
983
984 pub fn into_bytes(self) -> Vec<u8> {
985 self.0
986 }
987}
988
989impl From<Vec<u8>> for FieldElement {
990 fn from(bytes: Vec<u8>) -> Self {
991 Self::from_bytes(bytes)
992 }
993}
994
995impl From<&[u8]> for FieldElement {
996 fn from(bytes: &[u8]) -> Self {
997 Self::from_bytes(bytes)
998 }
999}
1000
1001#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1002pub struct GroupElement(pub Vec<u8>);
1003
1004impl GroupElement {
1005 pub fn from_bytes(bytes: impl Into<Vec<u8>>) -> Self {
1006 Self(bytes.into())
1007 }
1008
1009 pub fn as_bytes(&self) -> &[u8] {
1010 &self.0
1011 }
1012
1013 pub fn into_bytes(self) -> Vec<u8> {
1014 self.0
1015 }
1016}
1017
1018impl From<Vec<u8>> for GroupElement {
1019 fn from(bytes: Vec<u8>) -> Self {
1020 Self::from_bytes(bytes)
1021 }
1022}
1023
1024impl From<&[u8]> for GroupElement {
1025 fn from(bytes: &[u8]) -> Self {
1026 Self::from_bytes(bytes)
1027 }
1028}