subsoil/consensus/beefy/
witness.rs1use super::commitment::{Commitment, SignedCommitment};
16use alloc::vec::Vec;
17
18#[derive(Debug, PartialEq, Eq, codec::Encode, codec::Decode)]
28pub struct SignedCommitmentWitness<TBlockNumber, TSignatureAccumulator> {
29 pub commitment: Commitment<TBlockNumber>,
31
32 pub signed_by: Vec<bool>, pub signature_accumulator: TSignatureAccumulator,
38}
39
40impl<TBlockNumber, TSignatureAccumulator>
41 SignedCommitmentWitness<TBlockNumber, TSignatureAccumulator>
42{
43 pub fn from_signed<TSignatureAggregator, TSignature>(
52 signed: SignedCommitment<TBlockNumber, TSignature>,
53 aggregator: TSignatureAggregator,
54 ) -> (Self, Vec<Option<TSignature>>)
55 where
56 TSignatureAggregator: FnOnce(&[Option<TSignature>]) -> TSignatureAccumulator,
57 {
58 let SignedCommitment { commitment, signatures } = signed;
59 let signed_by = signatures.iter().map(|s| s.is_some()).collect();
60 let signature_accumulator = aggregator(&signatures);
61
62 (Self { commitment, signed_by, signature_accumulator }, signatures)
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use crate::core::Pair;
69 use crate::crypto_hashing::keccak_256;
70
71 use super::*;
72 use codec::Decode;
73
74 use crate::consensus::beefy::{
75 ecdsa_crypto::Signature as EcdsaSignature, known_payloads, Payload,
76 };
77
78 #[cfg(feature = "bls-experimental")]
79 use crate::consensus::beefy::bls_crypto::Signature as BlsSignature;
80
81 #[cfg(feature = "bls-experimental")]
82 use w3f_bls::{
83 single_pop_aggregator::SignatureAggregatorAssumingPoP, Message, SerializableToBytes,
84 Signed, TinyBLS381,
85 };
86
87 type TestCommitment = Commitment<u128>;
88
89 type TestEcdsaSignedCommitment = SignedCommitment<u128, EcdsaSignature>;
91 type TestEcdsaSignedCommitmentWitness =
92 SignedCommitmentWitness<u128, Vec<Option<EcdsaSignature>>>;
93
94 #[cfg(feature = "bls-experimental")]
95 #[derive(Clone, Debug, PartialEq, codec::Encode, codec::Decode)]
96 struct EcdsaBlsSignaturePair(EcdsaSignature, BlsSignature);
97
98 #[cfg(feature = "bls-experimental")]
100 type TestBlsSignedCommitment = SignedCommitment<u128, EcdsaBlsSignaturePair>;
101 #[cfg(feature = "bls-experimental")]
102 type TestBlsSignedCommitmentWitness = SignedCommitmentWitness<u128, Vec<u8>>;
103
104 fn mock_ecdsa_signatures() -> (EcdsaSignature, EcdsaSignature) {
106 let alice = crate::core::ecdsa::Pair::from_string("//Alice", None).unwrap();
107
108 let msg = keccak_256(b"This is the first message");
109 let sig1 = alice.sign_prehashed(&msg);
110
111 let msg = keccak_256(b"This is the second message");
112 let sig2 = alice.sign_prehashed(&msg);
113
114 (sig1.into(), sig2.into())
115 }
116
117 #[cfg(feature = "bls-experimental")]
120 fn mock_bls_signatures() -> (BlsSignature, BlsSignature) {
121 let alice = crate::core::bls::Pair::from_string("//Alice", None).unwrap();
122
123 let msg = b"This is the first message";
124 let sig1 = alice.sign(msg);
125
126 let msg = b"This is the second message";
127 let sig2 = alice.sign(msg);
128
129 (sig1.into(), sig2.into())
130 }
131
132 fn ecdsa_signed_commitment() -> TestEcdsaSignedCommitment {
133 let payload = Payload::from_single_entry(
134 known_payloads::MMR_ROOT_ID,
135 "Hello World!".as_bytes().to_vec(),
136 );
137 let commitment: TestCommitment =
138 Commitment { payload, block_number: 5, validator_set_id: 0 };
139
140 let sigs = mock_ecdsa_signatures();
141
142 SignedCommitment { commitment, signatures: vec![None, None, Some(sigs.0), Some(sigs.1)] }
143 }
144
145 #[cfg(feature = "bls-experimental")]
146 fn ecdsa_and_bls_signed_commitment() -> TestBlsSignedCommitment {
147 let payload = Payload::from_single_entry(
148 known_payloads::MMR_ROOT_ID,
149 "Hello World!".as_bytes().to_vec(),
150 );
151 let commitment: TestCommitment =
152 Commitment { payload, block_number: 5, validator_set_id: 0 };
153
154 let ecdsa_sigs = mock_ecdsa_signatures();
155 let bls_sigs = mock_bls_signatures();
156
157 SignedCommitment {
158 commitment,
159 signatures: vec![
160 None,
161 None,
162 Some(EcdsaBlsSignaturePair(ecdsa_sigs.0, bls_sigs.0)),
163 Some(EcdsaBlsSignaturePair(ecdsa_sigs.1, bls_sigs.1)),
164 ],
165 }
166 }
167
168 #[test]
169 fn should_convert_signed_commitment_to_witness() {
170 let signed = ecdsa_signed_commitment();
172
173 let (witness, signatures) =
175 TestEcdsaSignedCommitmentWitness::from_signed(signed, |sigs| sigs.to_vec());
176
177 assert_eq!(witness.signature_accumulator, signatures);
179 }
180
181 #[test]
182 #[cfg(feature = "bls-experimental")]
183 fn should_convert_dually_signed_commitment_to_witness() {
184 let signed = ecdsa_and_bls_signed_commitment();
186
187 let (witness, _signatures) =
189 TestBlsSignedCommitmentWitness::from_signed::<_, _>(signed, |sigs| {
191 let mut aggregatedsigs: SignatureAggregatorAssumingPoP<TinyBLS381> =
193 SignatureAggregatorAssumingPoP::new(Message::new(b"", b"mock payload"));
194
195 for sig in sigs {
196 match sig {
197 Some(sig) => {
198 let serialized_sig : Vec<u8> = (*sig.1).to_vec();
199 aggregatedsigs.add_signature(
200 &w3f_bls::Signature::<TinyBLS381>::from_bytes(
201 serialized_sig.as_slice()
202 ).unwrap()
203 );
204 },
205 None => (),
206 }
207 }
208 (&aggregatedsigs).signature().to_bytes()
209 });
210
211 w3f_bls::Signature::<TinyBLS381>::from_bytes(witness.signature_accumulator.as_slice())
214 .unwrap();
215 }
216
217 #[test]
218 fn should_encode_and_decode_witness() {
219 let signed = ecdsa_signed_commitment();
221 let (witness, _) = TestEcdsaSignedCommitmentWitness::from_signed::<_, _>(
222 signed,
223 |sigs: &[std::option::Option<EcdsaSignature>]| sigs.to_vec(),
224 );
225
226 let encoded = codec::Encode::encode(&witness);
228 let decoded = TestEcdsaSignedCommitmentWitness::decode(&mut &*encoded);
229
230 assert_eq!(decoded, Ok(witness));
232 assert_eq!(
233 encoded,
234 array_bytes::hex2bytes_unchecked(
235 "\
236 046d683048656c6c6f20576f726c642105000000000000000000000000000000000000000000000010\
237 0000010110000001558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c\
238 746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01012d6e1f8105c337a8\
239 6cdd9aaacdc496577f3db8c55ef9e6fd48f2c5c05a2274707491635d8ba3df64f324575b7b2a34487b\
240 ca2324b6a0046395a71681be3d0c2a00\
241 "
242 )
243 );
244 }
245}