// Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 // for time being assume the bandwidth credential consists of public identity of the requester // and private (though known... just go along with it) infinite bandwidth value // right now this has no double-spending protection, spender binding, etc // it's the simplest possible case use url::Url; use coconut_interface::{ Credential, Parameters, PrivateAttribute, PublicAttribute, Signature, VerificationKey, }; use crate::error::Error; use crate::utils::{obtain_aggregate_signature, prepare_credential_for_spending}; pub const BANDWIDTH_VALUE: u64 = 10 * 1024 * 1024 * 1024; // 10 GB pub const PUBLIC_ATTRIBUTES: u32 = 2; pub const PRIVATE_ATTRIBUTES: u32 = 2; pub const TOTAL_ATTRIBUTES: u32 = PUBLIC_ATTRIBUTES + PRIVATE_ATTRIBUTES; pub const SERIAL_NUMBER_LEN: usize = 47; pub const BINDING_NUMBER_LEN: usize = 47; pub const VOUCHER_INFO_LEN: usize = 47; pub struct BandwidthVoucherAttributes { // a random secret value generated by the client used for double-spending detection pub serial_number: PrivateAttribute, // a random secret value generated by the client used to bind multiple credentials together pub binding_number: PrivateAttribute, // the value (e.g., bandwidth) encoded in this voucher pub voucher_value: PublicAttribute, // a field with public information, e.g., type of voucher, epoch etc. pub voucher_info: PublicAttribute, } impl BandwidthVoucherAttributes { pub fn get_public_attributes(&self) -> Vec { vec![self.voucher_value, self.voucher_info] } pub fn get_private_attributes(&self) -> Vec { let mut priv_attributes = Vec::with_capacity(PRIVATE_ATTRIBUTES as usize); priv_attributes.push(self.serial_number); priv_attributes.push(self.binding_number); priv_attributes } } // TODO: this definitely has to be moved somewhere else. It's just a temporary solution pub async fn obtain_signature( params: &Parameters, attributes: &BandwidthVoucherAttributes, validators: &[Url], verification_key: &VerificationKey, ) -> Result { let public_attributes = attributes.get_public_attributes(); let private_attributes = attributes.get_private_attributes(); obtain_aggregate_signature( params, &public_attributes, &private_attributes, validators, verification_key, ) .await } pub fn prepare_for_spending( raw_identity: &[u8], signature: &Signature, attributes: &BandwidthVoucherAttributes, verification_key: &VerificationKey, ) -> Result { let public_attributes = vec![ raw_identity.to_vec(), BANDWIDTH_VALUE.to_be_bytes().to_vec(), ]; let params = Parameters::new(TOTAL_ATTRIBUTES)?; prepare_credential_for_spending( ¶ms, public_attributes, attributes.serial_number, attributes.binding_number, signature, verification_key, ) }