hotshot_types/traits/
signature_key.rs

1// Copyright (c) 2021-2024 Espresso Systems (espressosys.com)
2// This file is part of the HotShot repository.
3
4// You should have received a copy of the MIT License
5// along with the HotShot repository. If not, see <https://mit-license.org/>.
6
7//! Minimal compatibility over public key signatures
8
9// data is serialized as big-endian for signing purposes
10#![forbid(clippy::little_endian_bytes)]
11
12use std::{
13    fmt::{Debug, Display},
14    hash::Hash,
15};
16
17use alloy::primitives::U256;
18use ark_serialize::SerializationError;
19use bitvec::prelude::*;
20use committable::Committable;
21use jf_signature::SignatureError;
22use serde::{Deserialize, Serialize, de::DeserializeOwned};
23use tagged_base64::{TaggedBase64, Tb64Error};
24
25use super::EncodeBytes;
26use crate::{
27    bundle::Bundle,
28    data::VidCommitment,
29    light_client::{CircuitField, LightClientState, StakeTableState, ToFieldsLightClientCompat},
30    traits::node_implementation::NodeType,
31    utils::BuilderCommitment,
32};
33
34/// Type representing stake table entries in a `StakeTable`
35pub trait StakeTableEntryType<K> {
36    /// Get the stake value
37    fn stake(&self) -> U256;
38    /// Get the public key
39    fn public_key(&self) -> K;
40}
41
42/// Trait for abstracting private signature key
43pub trait PrivateSignatureKey:
44    Send + Sync + Sized + Clone + Debug + Eq + Hash + for<'a> TryFrom<&'a TaggedBase64>
45{
46    /// Serialize the private key into bytes
47    fn to_bytes(&self) -> Vec<u8>;
48
49    /// Deserialize the private key from bytes
50    /// # Errors
51    /// If deserialization fails.
52    fn from_bytes(bytes: &[u8]) -> anyhow::Result<Self>;
53
54    /// Serialize the private key into TaggedBase64 blob.
55    /// # Errors
56    /// If serialization fails.
57    fn to_tagged_base64(&self) -> Result<TaggedBase64, Tb64Error>;
58}
59
60/// Trait for abstracting public key signatures
61/// Self is the public key type
62pub trait SignatureKey:
63    Send
64    + Sync
65    + Clone
66    + Sized
67    + Debug
68    + Hash
69    + Serialize
70    + for<'a> Deserialize<'a>
71    + PartialEq
72    + Eq
73    + PartialOrd
74    + Ord
75    + Display
76    + ToFieldsLightClientCompat
77    + for<'a> TryFrom<&'a TaggedBase64>
78    + Into<TaggedBase64>
79{
80    /// The private key type for this signature algorithm
81    type PrivateKey: PrivateSignatureKey;
82    /// The type of the entry that contain both public key and stake value
83    type StakeTableEntry: StakeTableEntryType<Self>
84        + Send
85        + Sync
86        + Sized
87        + Clone
88        + Debug
89        + Hash
90        + Eq
91        + Serialize
92        + for<'a> Deserialize<'a>;
93    /// The verification key type
94    type VerificationKeyType: Debug
95        + Hash
96        + Clone
97        + Send
98        + Sync
99        + for<'a> Deserialize<'a>
100        + Serialize
101        + PartialEq
102        + Eq;
103    /// The type of the quorum certificate parameters used for assembled signature
104    type QcParams<'a>: Send + Sync + Sized + Clone + Debug + Hash;
105    /// The type of the assembled signature, without `BitVec`
106    type PureAssembledSignatureType: Send
107        + Sync
108        + Sized
109        + Clone
110        + Debug
111        + Hash
112        + PartialEq
113        + Eq
114        + Serialize
115        + for<'a> Deserialize<'a>
116        + Into<TaggedBase64>
117        + for<'a> TryFrom<&'a TaggedBase64>;
118    /// The type of the assembled qc: assembled signature + `BitVec`
119    type QcType: Send
120        + Sync
121        + Sized
122        + Clone
123        + Debug
124        + Hash
125        + PartialEq
126        + Eq
127        + Serialize
128        + for<'a> Deserialize<'a>;
129
130    /// Type of error that can occur when signing data
131    type SignError: std::error::Error + Send + Sync;
132
133    // Signature type represented as a vec/slice of bytes to let the implementer handle the nuances
134    // of serialization, to avoid Cryptographic pitfalls
135    /// Validate a signature
136    fn validate(&self, signature: &Self::PureAssembledSignatureType, data: &[u8]) -> bool;
137
138    /// Produce a signature
139    /// # Errors
140    /// If unable to sign the data with the key
141    fn sign(
142        private_key: &Self::PrivateKey,
143        data: &[u8],
144    ) -> Result<Self::PureAssembledSignatureType, Self::SignError>;
145
146    /// Produce a public key from a private key
147    fn from_private(private_key: &Self::PrivateKey) -> Self;
148    /// Serialize a public key to bytes
149    fn to_bytes(&self) -> Vec<u8>;
150    /// Deserialize a public key from bytes
151    /// # Errors
152    ///
153    /// Will return `Err` if deserialization fails
154    fn from_bytes(bytes: &[u8]) -> Result<Self, SerializationError>;
155
156    /// Generate a new key pair
157    fn generated_from_seed_indexed(seed: [u8; 32], index: u64) -> (Self, Self::PrivateKey);
158
159    /// get the stake table entry from the public key and stake value
160    fn stake_table_entry(&self, stake: U256) -> Self::StakeTableEntry;
161
162    /// only get the public key from the stake table entry
163    fn public_key(entry: &Self::StakeTableEntry) -> Self;
164
165    /// get the public parameter for the assembled signature checking
166    fn public_parameter(
167        stake_entries: &[Self::StakeTableEntry],
168        threshold: U256,
169    ) -> Self::QcParams<'_>;
170
171    /// check the quorum certificate for the assembled signature, returning `Ok(())` if it is valid.
172    ///
173    /// # Errors
174    /// Returns an error if the signature key fails to validate
175    fn check(
176        real_qc_pp: &Self::QcParams<'_>,
177        data: &[u8],
178        qc: &Self::QcType,
179    ) -> Result<(), SignatureError>;
180
181    /// Get the list of signers given a qc.
182    ///
183    /// # Errors
184    /// Returns an error if the inputs mismatch (e.g. wrong verifier parameter or original message).
185    fn signers(
186        real_qc_pp: &Self::QcParams<'_>,
187        qc: &Self::QcType,
188    ) -> Result<Vec<Self::VerificationKeyType>, SignatureError>;
189
190    /// get the assembled signature and the `BitVec` separately from the assembled signature
191    fn sig_proof(signature: &Self::QcType) -> (Self::PureAssembledSignatureType, BitVec);
192
193    /// assemble the signature from the partial signature and the indication of signers in `BitVec`
194    fn assemble(
195        real_qc_pp: &Self::QcParams<'_>,
196        signers: &BitSlice,
197        sigs: &[Self::PureAssembledSignatureType],
198    ) -> Self::QcType;
199
200    /// generates the genesis public key. Meant to be dummy/filler
201    #[must_use]
202    fn genesis_proposer_pk() -> Self;
203
204    /// convert the public key to verification key
205    fn to_verification_key(&self) -> Self::VerificationKeyType;
206}
207
208/// Builder Signature Key trait with minimal requirements
209pub trait BuilderSignatureKey:
210    Send
211    + Sync
212    + Clone
213    + Sized
214    + Debug
215    + Hash
216    + Serialize
217    + DeserializeOwned
218    + PartialEq
219    + Eq
220    + PartialOrd
221    + Ord
222    + Display
223{
224    /// The type of the keys builder would use to sign its messages
225    type BuilderPrivateKey: PrivateSignatureKey;
226
227    /// The type of the signature builder would use to sign its messages
228    type BuilderSignature: Send
229        + Sync
230        + Sized
231        + Clone
232        + Debug
233        + Eq
234        + Serialize
235        + for<'a> Deserialize<'a>
236        + Hash;
237
238    /// Type of error that can occur when signing data
239    type SignError: std::error::Error + Send + Sync;
240
241    /// validate the message with the builder's public key
242    fn validate_builder_signature(&self, signature: &Self::BuilderSignature, data: &[u8]) -> bool;
243
244    /// validate signature over sequencing fee information
245    /// with the builder's public key
246    fn validate_fee_signature<Metadata: EncodeBytes>(
247        &self,
248        signature: &Self::BuilderSignature,
249        fee_amount: u64,
250        metadata: &Metadata,
251    ) -> bool {
252        self.validate_builder_signature(signature, &aggregate_fee_data(fee_amount, metadata))
253    }
254
255    /// validate signature over sequencing fee information
256    /// with the builder's public key, including vid commitment
257    fn validate_fee_signature_with_vid_commitment<Metadata: EncodeBytes>(
258        &self,
259        signature: &Self::BuilderSignature,
260        fee_amount: u64,
261        metadata: &Metadata,
262        vid_commitment: &VidCommitment,
263    ) -> bool {
264        self.validate_builder_signature(
265            signature,
266            &aggregate_fee_data_with_vid_commitment(fee_amount, metadata, vid_commitment),
267        )
268    }
269
270    /// validate signature over sequencing fee information
271    /// with the builder's public key (marketplace version)
272    fn validate_sequencing_fee_signature_marketplace(
273        &self,
274        signature: &Self::BuilderSignature,
275        fee_amount: u64,
276        view_number: u64,
277    ) -> bool {
278        self.validate_builder_signature(
279            signature,
280            &aggregate_fee_data_marketplace(fee_amount, view_number),
281        )
282    }
283
284    /// validate the bundle's signature using the builder's public key
285    fn validate_bundle_signature<TYPES: NodeType<BuilderSignatureKey = Self>>(
286        &self,
287        bundle: Bundle<TYPES>,
288    ) -> bool where {
289        let commitments = bundle
290            .transactions
291            .iter()
292            .flat_map(|txn| <[u8; 32]>::from(txn.commit()))
293            .collect::<Vec<u8>>();
294
295        self.validate_builder_signature(&bundle.signature, &commitments)
296    }
297
298    /// validate signature over block information with the builder's public key
299    fn validate_block_info_signature(
300        &self,
301        signature: &Self::BuilderSignature,
302        block_size: u64,
303        fee_amount: u64,
304        payload_commitment: &BuilderCommitment,
305    ) -> bool {
306        self.validate_builder_signature(
307            signature,
308            &aggregate_block_info_data(block_size, fee_amount, payload_commitment),
309        )
310    }
311
312    /// sign the message with the builder's private key
313    /// # Errors
314    /// If unable to sign the data with the key
315    fn sign_builder_message(
316        private_key: &Self::BuilderPrivateKey,
317        data: &[u8],
318    ) -> Result<Self::BuilderSignature, Self::SignError>;
319
320    /// sign sequencing fee offer
321    /// # Errors
322    /// If unable to sign the data with the key
323    fn sign_fee<Metadata: EncodeBytes>(
324        private_key: &Self::BuilderPrivateKey,
325        fee_amount: u64,
326        metadata: &Metadata,
327    ) -> Result<Self::BuilderSignature, Self::SignError> {
328        Self::sign_builder_message(private_key, &aggregate_fee_data(fee_amount, metadata))
329    }
330
331    /// sign sequencing fee offer, with the payload commitment included
332    /// # Errors
333    /// If unable to sign the data with the key
334    fn sign_fee_with_vid_commitment<Metadata: EncodeBytes>(
335        private_key: &Self::BuilderPrivateKey,
336        fee_amount: u64,
337        metadata: &Metadata,
338        vid_commitment: &VidCommitment,
339    ) -> Result<Self::BuilderSignature, Self::SignError> {
340        Self::sign_builder_message(
341            private_key,
342            &aggregate_fee_data_with_vid_commitment(fee_amount, metadata, vid_commitment),
343        )
344    }
345
346    /// sign transactions (marketplace version)
347    /// # Errors
348    /// If unable to sign the data with the key
349    fn sign_bundle<TYPES: NodeType>(
350        private_key: &Self::BuilderPrivateKey,
351        transactions: &[TYPES::Transaction],
352    ) -> Result<Self::BuilderSignature, Self::SignError> {
353        let commitments = transactions
354            .iter()
355            .flat_map(|txn| <[u8; 32]>::from(txn.commit()))
356            .collect::<Vec<u8>>();
357
358        Self::sign_builder_message(private_key, &commitments)
359    }
360
361    /// sign information about offered block
362    /// # Errors
363    /// If unable to sign the data with the key
364    fn sign_block_info(
365        private_key: &Self::BuilderPrivateKey,
366        block_size: u64,
367        fee_amount: u64,
368        payload_commitment: &BuilderCommitment,
369    ) -> Result<Self::BuilderSignature, Self::SignError> {
370        Self::sign_builder_message(
371            private_key,
372            &aggregate_block_info_data(block_size, fee_amount, payload_commitment),
373        )
374    }
375
376    /// Generate a new key pair
377    fn generated_from_seed_indexed(seed: [u8; 32], index: u64) -> (Self, Self::BuilderPrivateKey);
378}
379
380/// Aggregate all inputs used for signature over fee data
381fn aggregate_fee_data<Metadata: EncodeBytes>(fee_amount: u64, metadata: &Metadata) -> Vec<u8> {
382    let mut fee_info = Vec::new();
383
384    fee_info.extend_from_slice(fee_amount.to_be_bytes().as_ref());
385    fee_info.extend_from_slice(metadata.encode().as_ref());
386
387    fee_info
388}
389
390/// Aggregate all inputs used for signature over fee data, including the vid commitment
391fn aggregate_fee_data_with_vid_commitment<Metadata: EncodeBytes>(
392    fee_amount: u64,
393    metadata: &Metadata,
394    vid_commitment: &VidCommitment,
395) -> Vec<u8> {
396    let mut fee_info = Vec::new();
397
398    fee_info.extend_from_slice(fee_amount.to_be_bytes().as_ref());
399    fee_info.extend_from_slice(metadata.encode().as_ref());
400    fee_info.extend_from_slice(vid_commitment.as_ref());
401
402    fee_info
403}
404
405/// Aggregate all inputs used for signature over fee data
406fn aggregate_fee_data_marketplace(fee_amount: u64, view_number: u64) -> Vec<u8> {
407    let mut fee_info = Vec::new();
408    fee_info.extend_from_slice(fee_amount.to_be_bytes().as_ref());
409    fee_info.extend_from_slice(view_number.to_be_bytes().as_ref());
410    fee_info
411}
412
413/// Aggregate all inputs used for signature over block info
414fn aggregate_block_info_data(
415    block_size: u64,
416    fee_amount: u64,
417    payload_commitment: &BuilderCommitment,
418) -> Vec<u8> {
419    let mut block_info = Vec::new();
420    block_info.extend_from_slice(block_size.to_be_bytes().as_ref());
421    block_info.extend_from_slice(fee_amount.to_be_bytes().as_ref());
422    block_info.extend_from_slice(payload_commitment.as_ref());
423    block_info
424}
425
426/// Light client state signature key with minimal requirements
427pub trait StateSignatureKey:
428    Send
429    + Sync
430    + Clone
431    + Sized
432    + Debug
433    + Hash
434    + Serialize
435    + for<'a> Deserialize<'a>
436    + PartialEq
437    + Eq
438    + Display
439    + Default
440    + ToFieldsLightClientCompat
441    + for<'a> TryFrom<&'a TaggedBase64>
442    + Into<TaggedBase64>
443{
444    /// The private key type
445    type StatePrivateKey: PrivateSignatureKey;
446
447    /// The type of the signature
448    type StateSignature: Send
449        + Sync
450        + Sized
451        + Clone
452        + Debug
453        + Eq
454        + Serialize
455        + for<'a> Deserialize<'a>
456        + Hash;
457
458    /// Type of error that can occur when signing data
459    type SignError: std::error::Error + Send + Sync;
460
461    /// Generate a new key pair
462    fn generated_from_seed_indexed(seed: [u8; 32], index: u64) -> (Self, Self::StatePrivateKey);
463}
464
465/// Light client V1 signature key functions. The replicas only sign the light client state.
466pub trait LCV1StateSignatureKey: StateSignatureKey {
467    /// Sign the state for legacy light client
468    fn sign_state(
469        private_key: &Self::StatePrivateKey,
470        light_client_state: &LightClientState,
471    ) -> Result<Self::StateSignature, Self::SignError>;
472
473    /// Verify the state signature for legacy light client
474    fn verify_state_sig(
475        &self,
476        signature: &Self::StateSignature,
477        light_client_state: &LightClientState,
478    ) -> bool;
479}
480
481/// Light client V2 signature key functions. The replicas sign the light client state and stake table state for the next update.
482pub trait LCV2StateSignatureKey: StateSignatureKey {
483    /// Sign the light client state
484    fn sign_state(
485        private_key: &Self::StatePrivateKey,
486        light_client_state: &LightClientState,
487        next_stake_table_state: &StakeTableState,
488    ) -> Result<Self::StateSignature, Self::SignError>;
489
490    /// Verify the light client state signature
491    fn verify_state_sig(
492        &self,
493        signature: &Self::StateSignature,
494        light_client_state: &LightClientState,
495        next_stake_table_state: &StakeTableState,
496    ) -> bool;
497}
498
499/// Light client V3 signature key functions. The replicas sign a keccak256 hash of ABI encodings of the light client state,
500/// next stake table state, and the auth root.
501pub trait LCV3StateSignatureKey: StateSignatureKey {
502    /// Sign the light client state
503    /// The input `msg` should be the keccak256 hash of ABI encodings of the light client state,
504    /// next stake table state, and the auth root.
505    fn sign_state(
506        private_key: &Self::StatePrivateKey,
507        msg: CircuitField,
508    ) -> Result<Self::StateSignature, Self::SignError>;
509
510    /// Verify the light client state signature
511    /// The input `msg` should be the keccak256 hash of ABI encodings of the light client state,
512    /// next stake table state, and the auth root.
513    fn verify_state_sig(&self, signature: &Self::StateSignature, msg: CircuitField) -> bool;
514}